diff -Nur kamikaze_7.09.orig/.config kamikaze_7.09/.config
--- kamikaze_7.09.orig/.config	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/.config	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,1012 @@
+#
+# Automatically generated make config: don't edit
+# OpenWrt version: 7.09 (Kamikaze)
+# Thu Jun 19 17:23:33 2008
+#
+CONFIG_HAVE_DOT_CONFIG=y
+# CONFIG_LINUX_2_6_AMCC is not set
+# CONFIG_LINUX_2_6_AU1000 is not set
+# CONFIG_LINUX_2_6_ATHEROS is not set
+# CONFIG_LINUX_2_6_AVR32 is not set
+# CONFIG_LINUX_2_4_BRCM is not set
+# CONFIG_LINUX_2_6_BRCM47XX is not set
+# CONFIG_LINUX_2_6_IXP4XX is not set
+# CONFIG_LINUX_2_6_MAGICBOX is not set
+# CONFIG_LINUX_2_6_RB532 is not set
+CONFIG_LINUX_2_6_X86=y
+# CONFIG_LINUX_2_6_ARM is not set
+# CONFIG_LINUX_2_6_CRIS is not set
+# CONFIG_LINUX_2_6_M68K is not set
+# CONFIG_LINUX_2_6_SH3 is not set
+# CONFIG_LINUX_2_6_SH3EB is not set
+# CONFIG_LINUX_2_6_SH4 is not set
+# CONFIG_LINUX_2_6_SH4EB is not set
+# CONFIG_LINUX_2_6_SPARC is not set
+# CONFIG_LINUX_2_6_AMCC_Default is not set
+# CONFIG_LINUX_2_6_AU1000_Atheros is not set
+# CONFIG_LINUX_2_6_AU1000_Broadcom is not set
+# CONFIG_LINUX_2_6_AU1000_Intel is not set
+# CONFIG_LINUX_2_6_ATHEROS_Default is not set
+# CONFIG_LINUX_2_6_AVR32_Default is not set
+# CONFIG_LINUX_2_4_BRCM_Broadcom is not set
+# CONFIG_LINUX_2_4_BRCM_BroadcomMimo is not set
+# CONFIG_LINUX_2_4_BRCM_Atheros is not set
+# CONFIG_LINUX_2_4_BRCM_None is not set
+# CONFIG_LINUX_2_4_BRCM_WL500G is not set
+# CONFIG_LINUX_2_4_BRCM_WL500GD is not set
+# CONFIG_LINUX_2_4_BRCM_WL500GP is not set
+# CONFIG_LINUX_2_4_BRCM_WL700GE is not set
+# CONFIG_LINUX_2_4_BRCM_WLHDD is not set
+# CONFIG_LINUX_2_4_BRCM_WRT54G3G is not set
+# CONFIG_LINUX_2_6_BRCM47XX_Atheros is not set
+# CONFIG_LINUX_2_6_BRCM47XX_None is not set
+# CONFIG_LINUX_2_6_BRCM47XX_WGT634U is not set
+# CONFIG_LINUX_2_6_BRCM47XX_WRTSL54GS is not set
+# CONFIG_LINUX_2_6_IXP4XX_Default is not set
+# CONFIG_LINUX_2_6_IXP4XX_NSLU2 is not set
+# CONFIG_LINUX_2_6_IXP4XX_NAS100d is not set
+# CONFIG_LINUX_2_6_IXP4XX_DSMG600RevA is not set
+# CONFIG_LINUX_2_6_MAGICBOX_Default is not set
+# CONFIG_LINUX_2_6_RB532_Default is not set
+# CONFIG_LINUX_2_6_X86_Generic is not set
+CONFIG_LINUX_2_6_X86_Alix=y
+# CONFIG_LINUX_2_6_X86_Soekris is not set
+CONFIG_LINUX_2_6=y
+CONFIG_PCI_SUPPORT=y
+CONFIG_PCMCIA_SUPPORT=y
+CONFIG_USB_SUPPORT=y
+CONFIG_ATM_SUPPORT=y
+CONFIG_VIDEO_SUPPORT=y
+CONFIG_USES_SQUASHFS=y
+CONFIG_USES_JFFS2=y
+CONFIG_USES_EXT2=y
+CONFIG_i386=y
+CONFIG_ARCH="i386"
+
+#
+# Target Images
+#
+# CONFIG_TARGET_ROOTFS_INITRAMFS is not set
+CONFIG_TARGET_ROOTFS_JFFS2=y
+CONFIG_TARGET_ROOTFS_SQUASHFS=y
+# CONFIG_TARGET_ROOTFS_TGZ is not set
+CONFIG_TARGET_ROOTFS_EXT2FS=y
+
+#
+# Image Options
+#
+CONFIG_X86_GRUB_IMAGES=y
+# CONFIG_X86_GRUB_IMAGES_PAD is not set
+CONFIG_X86_GRUB_BAUDRATE=38400
+CONFIG_X86_GRUB_KERNELPART=8
+CONFIG_X86_GRUB_ROOTPART="/dev/hda2"
+CONFIG_X86_GRUB_BOOTOPTS=""
+CONFIG_TARGET_ROOTFS_FSPART=55
+CONFIG_TARGET_ROOTFS_MAXINODE=1500
+# CONFIG_ALL is not set
+# CONFIG_DEVEL is not set
+# CONFIG_BROKEN is not set
+CONFIG_AUTOREBUILD=y
+# CONFIG_TAR_VERBOSITY is not set
+CONFIG_JLEVEL=1
+# CONFIG_CCACHE is not set
+CONFIG_SOURCE_FEEDS="https://svn.openwrt.org/openwrt/packages/"
+CONFIG_SOURCE_FEEDS_REV=""
+# CONFIG_NATIVE_TOOLCHAIN is not set
+CONFIG_BINUTILS_VERSION="2.17"
+CONFIG_EXTRA_GCC_CONFIG_OPTIONS=""
+CONFIG_INSTALL_LIBSTDCPP=y
+# CONFIG_GDB is not set
+CONFIG_LARGEFILE=y
+# CONFIG_C99_MATH is not set
+CONFIG_TARGET_OPTIMIZATION="-O2 -pipe -march=i486 -funit-at-a-time"
+CONFIG_GCC_VERSION="4.1.2"
+# CONFIG_IB is not set
+# CONFIG_SDK is not set
+# CONFIG_UCI_PRECONFIG is not set
+CONFIG_UCI_PRECONFIG_network_lan_proto="static"
+CONFIG_UCI_PRECONFIG_network_lan_ipaddr="192.168.1.1"
+CONFIG_UCI_PRECONFIG_network_lan_netmask="255.255.255.0"
+CONFIG_UCI_PRECONFIG_network_lan_gateway=""
+CONFIG_UCI_PRECONFIG_network_lan_dns=""
+
+#
+# Base system
+#
+CONFIG_DEFAULT_base-files=y
+CONFIG_DEFAULT_libgcc=y
+CONFIG_DEFAULT_uclibc=y
+CONFIG_DEFAULT_bridge=y
+CONFIG_DEFAULT_busybox=y
+CONFIG_DEFAULT_dnsmasq=y
+CONFIG_DEFAULT_dropbear=y
+CONFIG_DEFAULT_iptables=y
+CONFIG_DEFAULT_mtd=y
+CONFIG_PACKAGE_base-files=y
+# CONFIG_PACKAGE_br2684ctl is not set
+CONFIG_PACKAGE_bridge=y
+CONFIG_PACKAGE_busybox=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_DEVFS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_2_4_MODULES is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_2_6_MODULES=y
+
+#
+# Configuration
+#
+CONFIG_BUSYBOX_CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_BUSYBOX_CONFIG_NITPICK is not set
+# CONFIG_BUSYBOX_CONFIG_DESKTOP is not set
+CONFIG_BUSYBOX_CONFIG_SHOW_USAGE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_COMPRESS_USAGE=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_BUSYBOX_CONFIG_LOCALE_SUPPORT is not set
+CONFIG_BUSYBOX_CONFIG_GETOPT_LONG=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_DEVPTS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_SUID=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SUID_CONFIG is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_HAVE_RPC=y
+# CONFIG_BUSYBOX_CONFIG_SELINUX is not set
+CONFIG_BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+
+#
+# Build Options
+#
+# CONFIG_BUSYBOX_CONFIG_STATIC is not set
+# CONFIG_BUSYBOX_CONFIG_BUILD_LIBBUSYBOX is not set
+CONFIG_BUSYBOX_CONFIG_LFS=y
+# CONFIG_BUSYBOX_CONFIG_BUILD_AT_ONCE is not set
+
+#
+# Debugging Options
+#
+# CONFIG_BUSYBOX_CONFIG_DEBUG is not set
+CONFIG_BUSYBOX_CONFIG_INCLUDE_SUSv2=y
+
+#
+# Installation Options
+#
+# CONFIG_BUSYBOX_CONFIG_INSTALL_NO_USR is not set
+CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS=y
+# CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_DONT is not set
+CONFIG_BUSYBOX_CONFIG_PREFIX="./_install"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_BUSYBOX_CONFIG_PASSWORD_MINLEN=6
+CONFIG_BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED=2
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_BUSYBOX_CONFIG_AR is not set
+CONFIG_BUSYBOX_CONFIG_BUNZIP2=y
+# CONFIG_BUSYBOX_CONFIG_CPIO is not set
+# CONFIG_BUSYBOX_CONFIG_DPKG is not set
+# CONFIG_BUSYBOX_CONFIG_DPKG_DEB is not set
+CONFIG_BUSYBOX_CONFIG_GUNZIP=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_GUNZIP_UNCOMPRESS=y
+CONFIG_BUSYBOX_CONFIG_GZIP=y
+CONFIG_BUSYBOX_CONFIG_IPKG=y
+# CONFIG_BUSYBOX_CONFIG_RPM2CPIO is not set
+# CONFIG_BUSYBOX_CONFIG_RPM is not set
+CONFIG_BUSYBOX_CONFIG_TAR=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_CREATE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_BZIP2=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_LZMA is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_FROM=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_GZIP=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_COMPRESS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_BUSYBOX_CONFIG_UNCOMPRESS is not set
+# CONFIG_BUSYBOX_CONFIG_UNLZMA is not set
+# CONFIG_BUSYBOX_CONFIG_UNZIP is not set
+
+#
+# Common options for cpio and tar
+#
+# CONFIG_BUSYBOX_CONFIG_FEATURE_UNARCHIVE_TAPE is not set
+
+#
+# Coreutils
+#
+CONFIG_BUSYBOX_CONFIG_BASENAME=y
+# CONFIG_BUSYBOX_CONFIG_CAL is not set
+CONFIG_BUSYBOX_CONFIG_CAT=y
+# CONFIG_BUSYBOX_CONFIG_CATV is not set
+CONFIG_BUSYBOX_CONFIG_CHGRP=y
+CONFIG_BUSYBOX_CONFIG_CHMOD=y
+CONFIG_BUSYBOX_CONFIG_CHOWN=y
+CONFIG_BUSYBOX_CONFIG_CHROOT=y
+# CONFIG_BUSYBOX_CONFIG_CKSUM is not set
+# CONFIG_BUSYBOX_CONFIG_CMP is not set
+# CONFIG_BUSYBOX_CONFIG_COMM is not set
+CONFIG_BUSYBOX_CONFIG_CP=y
+CONFIG_BUSYBOX_CONFIG_CUT=y
+CONFIG_BUSYBOX_CONFIG_DATE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_DATE_ISOFMT=y
+CONFIG_BUSYBOX_CONFIG_DD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_DD_IBS_OBS is not set
+CONFIG_BUSYBOX_CONFIG_DF=y
+# CONFIG_BUSYBOX_CONFIG_DIFF is not set
+CONFIG_BUSYBOX_CONFIG_DIRNAME=y
+# CONFIG_BUSYBOX_CONFIG_DOS2UNIX is not set
+CONFIG_BUSYBOX_CONFIG_DU=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
+CONFIG_BUSYBOX_CONFIG_ECHO=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_BUSYBOX_CONFIG_ENV=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
+CONFIG_BUSYBOX_CONFIG_EXPR=y
+# CONFIG_BUSYBOX_CONFIG_EXPR_MATH_SUPPORT_64 is not set
+CONFIG_BUSYBOX_CONFIG_FALSE=y
+# CONFIG_BUSYBOX_CONFIG_FOLD is not set
+CONFIG_BUSYBOX_CONFIG_HEAD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_HEAD=y
+CONFIG_BUSYBOX_CONFIG_HOSTID=y
+CONFIG_BUSYBOX_CONFIG_ID=y
+# CONFIG_BUSYBOX_CONFIG_INSTALL is not set
+CONFIG_BUSYBOX_CONFIG_LENGTH=y
+CONFIG_BUSYBOX_CONFIG_LN=y
+# CONFIG_BUSYBOX_CONFIG_LOGNAME is not set
+CONFIG_BUSYBOX_CONFIG_LS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_FOLLOWLINKS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_COLOR=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+CONFIG_BUSYBOX_CONFIG_MD5SUM=y
+CONFIG_BUSYBOX_CONFIG_MKDIR=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
+CONFIG_BUSYBOX_CONFIG_MKFIFO=y
+CONFIG_BUSYBOX_CONFIG_MKNOD=y
+CONFIG_BUSYBOX_CONFIG_MV=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS is not set
+# CONFIG_BUSYBOX_CONFIG_NICE is not set
+# CONFIG_BUSYBOX_CONFIG_NOHUP is not set
+# CONFIG_BUSYBOX_CONFIG_OD is not set
+# CONFIG_BUSYBOX_CONFIG_PRINTENV is not set
+CONFIG_BUSYBOX_CONFIG_PRINTF=y
+CONFIG_BUSYBOX_CONFIG_PWD=y
+# CONFIG_BUSYBOX_CONFIG_REALPATH is not set
+CONFIG_BUSYBOX_CONFIG_RM=y
+CONFIG_BUSYBOX_CONFIG_RMDIR=y
+CONFIG_BUSYBOX_CONFIG_SEQ=y
+# CONFIG_BUSYBOX_CONFIG_SHA1SUM is not set
+CONFIG_BUSYBOX_CONFIG_SLEEP=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP=y
+CONFIG_BUSYBOX_CONFIG_SORT=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SORT_BIG is not set
+# CONFIG_BUSYBOX_CONFIG_STAT is not set
+# CONFIG_BUSYBOX_CONFIG_STTY is not set
+# CONFIG_BUSYBOX_CONFIG_SUM is not set
+CONFIG_BUSYBOX_CONFIG_SYNC=y
+CONFIG_BUSYBOX_CONFIG_TAIL=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_TAIL=y
+CONFIG_BUSYBOX_CONFIG_TEE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
+CONFIG_BUSYBOX_CONFIG_TEST=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TEST_64 is not set
+CONFIG_BUSYBOX_CONFIG_TOUCH=y
+CONFIG_BUSYBOX_CONFIG_TR=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TR_CLASSES is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TR_EQUIV is not set
+CONFIG_BUSYBOX_CONFIG_TRUE=y
+# CONFIG_BUSYBOX_CONFIG_TTY is not set
+CONFIG_BUSYBOX_CONFIG_UNAME=y
+CONFIG_BUSYBOX_CONFIG_UNIQ=y
+# CONFIG_BUSYBOX_CONFIG_USLEEP is not set
+# CONFIG_BUSYBOX_CONFIG_UUDECODE is not set
+# CONFIG_BUSYBOX_CONFIG_UUENCODE is not set
+# CONFIG_BUSYBOX_CONFIG_WATCH is not set
+CONFIG_BUSYBOX_CONFIG_WC=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_WC_LARGE is not set
+# CONFIG_BUSYBOX_CONFIG_WHO is not set
+# CONFIG_BUSYBOX_CONFIG_WHOAMI is not set
+CONFIG_BUSYBOX_CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_PRESERVE_HARDLINKS=y
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Common options for md5sum, sha1sum
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
+
+#
+# Console Utilities
+#
+# CONFIG_BUSYBOX_CONFIG_CHVT is not set
+CONFIG_BUSYBOX_CONFIG_CLEAR=y
+# CONFIG_BUSYBOX_CONFIG_DEALLOCVT is not set
+# CONFIG_BUSYBOX_CONFIG_DUMPKMAP is not set
+# CONFIG_BUSYBOX_CONFIG_LOADFONT is not set
+# CONFIG_BUSYBOX_CONFIG_LOADKMAP is not set
+# CONFIG_BUSYBOX_CONFIG_OPENVT is not set
+CONFIG_BUSYBOX_CONFIG_RESET=y
+# CONFIG_BUSYBOX_CONFIG_RESIZE is not set
+# CONFIG_BUSYBOX_CONFIG_SETCONSOLE is not set
+# CONFIG_BUSYBOX_CONFIG_SETKEYCODES is not set
+# CONFIG_BUSYBOX_CONFIG_SETLOGCONS is not set
+
+#
+# Debian Utilities
+#
+CONFIG_BUSYBOX_CONFIG_MKTEMP=y
+# CONFIG_BUSYBOX_CONFIG_PIPE_PROGRESS is not set
+# CONFIG_BUSYBOX_CONFIG_READLINK is not set
+# CONFIG_BUSYBOX_CONFIG_RUN_PARTS is not set
+# CONFIG_BUSYBOX_CONFIG_START_STOP_DAEMON is not set
+CONFIG_BUSYBOX_CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_BUSYBOX_CONFIG_AWK=y
+CONFIG_BUSYBOX_CONFIG_AWX=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_AWK_MATH=y
+# CONFIG_BUSYBOX_CONFIG_ED is not set
+# CONFIG_BUSYBOX_CONFIG_PATCH is not set
+CONFIG_BUSYBOX_CONFIG_SED=y
+CONFIG_BUSYBOX_CONFIG_VI=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_COLON=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SEARCH=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_READONLY=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SET=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC=y
+
+#
+# Finding Utilities
+#
+CONFIG_BUSYBOX_CONFIG_FIND=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PRINT0=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MTIME is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MMIN is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PERM=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_TYPE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_XDEV=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_NEWER is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_INUM is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_BUSYBOX_CONFIG_GREP=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_FGREP_ALIAS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT=y
+CONFIG_BUSYBOX_CONFIG_XARGS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
+
+#
+# Init Utilities
+#
+CONFIG_BUSYBOX_CONFIG_INIT=y
+# CONFIG_BUSYBOX_CONFIG_DEBUG_INIT is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_USE_INITTAB=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_SCTTY is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_COREDUMPS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_INITRD is not set
+CONFIG_BUSYBOX_CONFIG_HALT=y
+CONFIG_BUSYBOX_CONFIG_MESG=y
+
+#
+# Login/Password Management Utilities
+#
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS is not set
+# CONFIG_BUSYBOX_CONFIG_USE_BB_PWD_GRP is not set
+# CONFIG_BUSYBOX_CONFIG_ADDGROUP is not set
+# CONFIG_BUSYBOX_CONFIG_DELGROUP is not set
+# CONFIG_BUSYBOX_CONFIG_ADDUSER is not set
+# CONFIG_BUSYBOX_CONFIG_DELUSER is not set
+# CONFIG_BUSYBOX_CONFIG_GETTY is not set
+# CONFIG_BUSYBOX_CONFIG_LOGIN is not set
+CONFIG_BUSYBOX_CONFIG_PASSWD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK=y
+# CONFIG_BUSYBOX_CONFIG_SU is not set
+# CONFIG_BUSYBOX_CONFIG_SULOGIN is not set
+# CONFIG_BUSYBOX_CONFIG_VLOCK is not set
+
+#
+# Linux Ext2 FS Progs
+#
+# CONFIG_BUSYBOX_CONFIG_CHATTR is not set
+# CONFIG_BUSYBOX_CONFIG_FSCK is not set
+# CONFIG_BUSYBOX_CONFIG_LSATTR is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_BUSYBOX_CONFIG_INSMOD=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+CONFIG_BUSYBOX_CONFIG_RMMOD=y
+CONFIG_BUSYBOX_CONFIG_LSMOD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y
+# CONFIG_BUSYBOX_CONFIG_MODPROBE is not set
+
+#
+# Options common to multiple modutils
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
+
+#
+# Linux System Utilities
+#
+CONFIG_BUSYBOX_CONFIG_DMESG=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_DMESG_PRETTY=y
+# CONFIG_BUSYBOX_CONFIG_FBSET is not set
+# CONFIG_BUSYBOX_CONFIG_FDFLUSH is not set
+# CONFIG_BUSYBOX_CONFIG_FDFORMAT is not set
+# CONFIG_BUSYBOX_CONFIG_FDISK is not set
+CONFIG_BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
+# CONFIG_BUSYBOX_CONFIG_FREERAMDISK is not set
+# CONFIG_BUSYBOX_CONFIG_FSCK_MINIX is not set
+# CONFIG_BUSYBOX_CONFIG_MKFS_MINIX is not set
+# CONFIG_BUSYBOX_CONFIG_GETOPT is not set
+CONFIG_BUSYBOX_CONFIG_HEXDUMP=y
+# CONFIG_BUSYBOX_CONFIG_HWCLOCK is not set
+# CONFIG_BUSYBOX_CONFIG_IPCRM is not set
+# CONFIG_BUSYBOX_CONFIG_IPCS is not set
+# CONFIG_BUSYBOX_CONFIG_LOSETUP is not set
+# CONFIG_BUSYBOX_CONFIG_MDEV is not set
+# CONFIG_BUSYBOX_CONFIG_MKSWAP is not set
+# CONFIG_BUSYBOX_CONFIG_MORE is not set
+CONFIG_BUSYBOX_CONFIG_MOUNT=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_NFS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FLAGS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB=y
+CONFIG_BUSYBOX_CONFIG_PIVOT_ROOT=y
+CONFIG_BUSYBOX_CONFIG_RDATE=y
+# CONFIG_BUSYBOX_CONFIG_READPROFILE is not set
+# CONFIG_BUSYBOX_CONFIG_SETARCH is not set
+# CONFIG_BUSYBOX_CONFIG_SWAPONOFF is not set
+CONFIG_BUSYBOX_CONFIG_SWITCH_ROOT=y
+CONFIG_BUSYBOX_CONFIG_UMOUNT=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_UMOUNT_ALL=y
+
+#
+# Common options for mount/umount
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_BUSYBOX_CONFIG_ADJTIMEX is not set
+# CONFIG_BUSYBOX_CONFIG_BBCONFIG is not set
+CONFIG_BUSYBOX_CONFIG_CROND=y
+# CONFIG_BUSYBOX_CONFIG_DEBUG_CROND_OPTION is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_BUSYBOX_CONFIG_CRONTAB=y
+# CONFIG_BUSYBOX_CONFIG_DC is not set
+# CONFIG_BUSYBOX_CONFIG_DEVFSD is not set
+# CONFIG_BUSYBOX_CONFIG_EJECT is not set
+# CONFIG_BUSYBOX_CONFIG_LAST is not set
+CONFIG_BUSYBOX_CONFIG_LESS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_MAXLINES=9999999
+# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_FLAGS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_FLAGCS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_MARKS is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_REGEXP is not set
+# CONFIG_BUSYBOX_CONFIG_HDPARM is not set
+CONFIG_BUSYBOX_CONFIG_LOCK=y
+# CONFIG_BUSYBOX_CONFIG_MAKEDEVS is not set
+# CONFIG_BUSYBOX_CONFIG_MOUNTPOINT is not set
+# CONFIG_BUSYBOX_CONFIG_MT is not set
+# CONFIG_BUSYBOX_CONFIG_NMETER is not set
+# CONFIG_BUSYBOX_CONFIG_RAIDAUTORUN is not set
+# CONFIG_BUSYBOX_CONFIG_RUNLEVEL is not set
+# CONFIG_BUSYBOX_CONFIG_RX is not set
+CONFIG_BUSYBOX_CONFIG_STRINGS=y
+# CONFIG_BUSYBOX_CONFIG_SETSID is not set
+# CONFIG_BUSYBOX_CONFIG_TASKSET is not set
+CONFIG_BUSYBOX_CONFIG_TIME=y
+CONFIG_BUSYBOX_CONFIG_WATCHDOG=y
+
+#
+# Networking Utilities
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_IPV6=y
+# CONFIG_BUSYBOX_CONFIG_ARP is not set
+CONFIG_BUSYBOX_CONFIG_ARPING=y
+# CONFIG_BUSYBOX_CONFIG_DNSD is not set
+# CONFIG_BUSYBOX_CONFIG_ETHER_WAKE is not set
+# CONFIG_BUSYBOX_CONFIG_FAKEIDENTD is not set
+# CONFIG_BUSYBOX_CONFIG_FTPGET is not set
+# CONFIG_BUSYBOX_CONFIG_FTPPUT is not set
+# CONFIG_BUSYBOX_CONFIG_HOSTNAME is not set
+CONFIG_BUSYBOX_CONFIG_HTTPD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_CGI=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y
+CONFIG_BUSYBOX_CONFIG_IFCONFIG=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_STATUS=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_HW=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
+# CONFIG_BUSYBOX_CONFIG_IFUPDOWN is not set
+# CONFIG_BUSYBOX_CONFIG_INETD is not set
+# CONFIG_BUSYBOX_CONFIG_IP is not set
+# CONFIG_BUSYBOX_CONFIG_IPCALC is not set
+# CONFIG_BUSYBOX_CONFIG_NAMEIF is not set
+CONFIG_BUSYBOX_CONFIG_NC=y
+CONFIG_BUSYBOX_CONFIG_NETMSG=y
+# CONFIG_BUSYBOX_CONFIG_NC_SERVER is not set
+# CONFIG_BUSYBOX_CONFIG_NC_EXTRA is not set
+CONFIG_BUSYBOX_CONFIG_NETSTAT=y
+CONFIG_BUSYBOX_CONFIG_NSLOOKUP=y
+CONFIG_BUSYBOX_CONFIG_PING=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_PING=y
+CONFIG_BUSYBOX_CONFIG_PING6=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_PING6=y
+CONFIG_BUSYBOX_CONFIG_ROUTE=y
+CONFIG_BUSYBOX_CONFIG_TELNET=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TELNET_TTYPE=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
+CONFIG_BUSYBOX_CONFIG_TELNETD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE=y
+# CONFIG_BUSYBOX_CONFIG_TFTP is not set
+CONFIG_BUSYBOX_CONFIG_TRACEROUTE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
+# CONFIG_BUSYBOX_CONFIG_APP_UDHCPD is not set
+CONFIG_BUSYBOX_CONFIG_APP_UDHCPC=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCP_SYSLOG is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCP_DEBUG is not set
+CONFIG_BUSYBOX_CONFIG_VCONFIG=y
+CONFIG_BUSYBOX_CONFIG_WGET=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_STATUSBAR=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_IP6_LITERAL=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS=y
+# CONFIG_BUSYBOX_CONFIG_ZCIP is not set
+
+#
+# Process Utilities
+#
+CONFIG_BUSYBOX_CONFIG_FREE=y
+# CONFIG_BUSYBOX_CONFIG_FUSER is not set
+CONFIG_BUSYBOX_CONFIG_KILL=y
+CONFIG_BUSYBOX_CONFIG_KILLALL=y
+CONFIG_BUSYBOX_CONFIG_KILLALL5=y
+CONFIG_BUSYBOX_CONFIG_PIDOF=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_PIDOF_SINGLE is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_PIDOF_OMIT is not set
+CONFIG_BUSYBOX_CONFIG_PS=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_PS_WIDE=y
+# CONFIG_BUSYBOX_CONFIG_RENICE is not set
+CONFIG_BUSYBOX_CONFIG_BB_SYSCTL=y
+CONFIG_BUSYBOX_CONFIG_TOP=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_BUSYBOX_CONFIG_UPTIME=y
+
+#
+# Shells
+#
+CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_ASH=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_LASH is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_MSH is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_NONE is not set
+CONFIG_BUSYBOX_CONFIG_ASH=y
+
+#
+# Ash Shell Options
+#
+CONFIG_BUSYBOX_CONFIG_ASH_JOB_CONTROL=y
+# CONFIG_BUSYBOX_CONFIG_ASH_READ_NCHARS is not set
+CONFIG_BUSYBOX_CONFIG_ASH_READ_TIMEOUT=y
+CONFIG_BUSYBOX_CONFIG_ASH_ALIAS=y
+CONFIG_BUSYBOX_CONFIG_ASH_MATH_SUPPORT=y
+# CONFIG_BUSYBOX_CONFIG_ASH_MATH_SUPPORT_64 is not set
+CONFIG_BUSYBOX_CONFIG_ASH_GETOPTS=y
+CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_ECHO=y
+CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_TEST=y
+CONFIG_BUSYBOX_CONFIG_ASH_CMDCMD=y
+# CONFIG_BUSYBOX_CONFIG_ASH_MAIL is not set
+CONFIG_BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+# CONFIG_BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_BUSYBOX_CONFIG_ASH_EXPAND_PRMT is not set
+# CONFIG_BUSYBOX_CONFIG_HUSH is not set
+# CONFIG_BUSYBOX_CONFIG_LASH is not set
+# CONFIG_BUSYBOX_CONFIG_MSH is not set
+
+#
+# Bourne Shell Options
+#
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING_VI is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_COMMAND_HISTORY=15
+# CONFIG_BUSYBOX_CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set
+CONFIG_BUSYBOX_CONFIG_FEATURE_SH_FANCY_PROMPT=y
+
+#
+# System Logging Utilities
+#
+CONFIG_BUSYBOX_CONFIG_SYSLOGD=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_ROTATE_LOGFILE=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_REMOTE_LOG=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG=y
+CONFIG_BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16
+CONFIG_BUSYBOX_CONFIG_LOGREAD=y
+# CONFIG_BUSYBOX_CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+CONFIG_BUSYBOX_CONFIG_KLOGD=y
+CONFIG_BUSYBOX_CONFIG_LOGGER=y
+
+#
+# Runit Utilities
+#
+# CONFIG_BUSYBOX_CONFIG_RUNSV is not set
+# CONFIG_BUSYBOX_CONFIG_RUNSVDIR is not set
+# CONFIG_BUSYBOX_CONFIG_SV is not set
+# CONFIG_BUSYBOX_CONFIG_SVLOGD is not set
+# CONFIG_BUSYBOX_CONFIG_CHPST is not set
+# CONFIG_BUSYBOX_CONFIG_SETUIDGID is not set
+# CONFIG_BUSYBOX_CONFIG_ENVUIDGID is not set
+# CONFIG_BUSYBOX_CONFIG_ENVDIR is not set
+# CONFIG_BUSYBOX_CONFIG_SOFTLIMIT is not set
+CONFIG_PACKAGE_dnsmasq=m
+CONFIG_PACKAGE_dropbear=y
+CONFIG_PACKAGE_iptables=y
+# CONFIG_PACKAGE_iptables-mod-conntrack is not set
+# CONFIG_PACKAGE_iptables-mod-extra is not set
+# CONFIG_PACKAGE_iptables-mod-filter is not set
+# CONFIG_PACKAGE_iptables-mod-imq is not set
+# CONFIG_PACKAGE_iptables-mod-ipopt is not set
+# CONFIG_PACKAGE_iptables-mod-iprange is not set
+# CONFIG_PACKAGE_iptables-mod-ipsec is not set
+# CONFIG_PACKAGE_iptables-mod-ipset is not set
+# CONFIG_PACKAGE_iptables-mod-nat is not set
+# CONFIG_PACKAGE_iptables-mod-ulog is not set
+# CONFIG_PACKAGE_iptables-utils is not set
+CONFIG_PACKAGE_libgcc=y
+CONFIG_PACKAGE_libpthread=m
+# CONFIG_PACKAGE_libssp is not set
+CONFIG_PACKAGE_libstdcpp=m
+CONFIG_PACKAGE_mtd=y
+# CONFIG_PACKAGE_qos-scripts is not set
+CONFIG_PACKAGE_uclibc=y
+CONFIG_PACKAGE_wireless-tools=y
+
+#
+# Utilities
+#
+CONFIG_DEFAULT_hotplug2=y
+CONFIG_DEFAULT_udevtrigger=y
+# CONFIG_PACKAGE_cfdisk is not set
+# CONFIG_PACKAGE_comgt is not set
+CONFIG_PACKAGE_cryptotest-bgp=y
+# CONFIG_PACKAGE_dropbearconvert is not set
+CONFIG_PACKAGE_e2fsprogs=y
+CONFIG_PACKAGE_fdisk=y
+# CONFIG_PACKAGE_fuse-utils is not set
+CONFIG_PACKAGE_hotplug2=y
+# CONFIG_PACKAGE_kexec-tools is not set
+# CONFIG_PACKAGE_losetup is not set
+CONFIG_PACKAGE_openssl-util=y
+# CONFIG_PACKAGE_pcmcia-cs is not set
+# CONFIG_PACKAGE_qc-usb-utils is not set
+CONFIG_PACKAGE_resize2fs=y
+# CONFIG_PACKAGE_robocfg is not set
+CONFIG_PACKAGE_screen=y
+# CONFIG_PACKAGE_shfs-utils is not set
+# CONFIG_PACKAGE_spca5xx-view is not set
+# CONFIG_PACKAGE_swap-utils is not set
+CONFIG_PACKAGE_tune2fs=y
+# CONFIG_PACKAGE_udev is not set
+CONFIG_PACKAGE_udevtrigger=y
+
+#
+# Libraries
+#
+CONFIG_DEFAULT_libopenssl-cryptodev=y
+
+#
+# openssl
+#
+CONFIG_PACKAGE_libopenssl=y
+CONFIG_PACKAGE_libopenssl-cryptodev=y
+# CONFIG_PACKAGE_libblkid is not set
+# CONFIG_PACKAGE_libfuse is not set
+CONFIG_PACKAGE_libgmp=m
+# CONFIG_PACKAGE_libjson is not set
+CONFIG_PACKAGE_libncurses=y
+CONFIG_PACKAGE_libpcap=y
+CONFIG_PACKAGE_libuuid=y
+# CONFIG_PACKAGE_linux-atm is not set
+CONFIG_PACKAGE_zlib=y
+
+#
+# Network
+#
+CONFIG_DEFAULT_ppp=y
+CONFIG_DEFAULT_ppp-mod-pppoe=y
+
+#
+# VPN
+#
+CONFIG_PACKAGE_openvpn=m
+# CONFIG_PACKAGE_openvpn-easy-rsa is not set
+# CONFIG_PACKAGE_arptables is not set
+# CONFIG_PACKAGE_chat is not set
+# CONFIG_PACKAGE_ebtables is not set
+# CONFIG_PACKAGE_genl is not set
+# CONFIG_PACKAGE_hostap-utils is not set
+CONFIG_PACKAGE_hostapd=m
+CONFIG_PACKAGE_hostapd-mini=m
+CONFIG_PACKAGE_hostapd-utils=m
+# CONFIG_PACKAGE_ifenslave is not set
+CONFIG_PACKAGE_ip=y
+CONFIG_PACKAGE_ip6tables=m
+CONFIG_PACKAGE_ipsec-tools=m
+CONFIG_PACKAGE_iptraf=y
+CONFIG_PACKAGE_isakmpd=m
+CONFIG_PACKAGE_keynote=m
+CONFIG_PACKAGE_netperf=y
+CONFIG_PACKAGE_olsrd=y
+CONFIG_PACKAGE_olsrd-mod-bmf=m
+CONFIG_PACKAGE_olsrd-mod-dot-draw=m
+CONFIG_PACKAGE_olsrd-mod-dyn-gw=m
+CONFIG_PACKAGE_olsrd-mod-httpinfo=y
+CONFIG_PACKAGE_olsrd-mod-nameservice=m
+CONFIG_PACKAGE_olsrd-mod-secure=m
+CONFIG_PACKAGE_olsrd-mod-txtinfo=m
+CONFIG_PACKAGE_ppp=y
+# CONFIG_PACKAGE_ppp-mod-pppoa is not set
+CONFIG_PACKAGE_ppp-mod-pppoe=y
+# CONFIG_PACKAGE_ppp-mod-radius is not set
+# CONFIG_PACKAGE_pppdump is not set
+# CONFIG_PACKAGE_pppstats is not set
+# CONFIG_PACKAGE_pptp is not set
+CONFIG_PACKAGE_tc=m
+CONFIG_PACKAGE_tcpdump=y
+CONFIG_PACKAGE_wpa-supplicant=m
+CONFIG_PACKAGE_wpa-cli=m
+CONFIG_PACKAGE_zd1211-firmware=m
+
+#
+# Kernel modules
+#
+CONFIG_DEFAULT_kmod-ipt-nathelper=y
+CONFIG_DEFAULT_kmod-natsemi=y
+CONFIG_DEFAULT_kmod-via-rhine=y
+CONFIG_DEFAULT_kmod-ne2k-pci=y
+CONFIG_DEFAULT_kmod-hw-rng=y
+CONFIG_DEFAULT_kmod-hw-crypto=y
+CONFIG_DEFAULT_kmod-linux-ocf=y
+CONFIG_DEFAULT_kmod-leds-alix=y
+
+#
+# Block Devices
+#
+CONFIG_PACKAGE_kmod-ata-piix=m
+CONFIG_PACKAGE_kmod-libata=m
+CONFIG_PACKAGE_kmod-pata-artop=m
+
+#
+# Filesystems
+#
+CONFIG_PACKAGE_kmod-fs-cifs=m
+CONFIG_PACKAGE_kmod-fs-ext2=m
+CONFIG_PACKAGE_kmod-fs-ext3=m
+CONFIG_PACKAGE_kmod-fs-hfsplus=m
+CONFIG_PACKAGE_kmod-fs-isofs=m
+CONFIG_PACKAGE_kmod-fs-minix=m
+CONFIG_PACKAGE_kmod-fs-msdos=m
+CONFIG_PACKAGE_kmod-fs-nfs=m
+CONFIG_PACKAGE_kmod-fs-nfsd=m
+CONFIG_PACKAGE_kmod-fs-udf=m
+CONFIG_PACKAGE_kmod-fs-vfat=m
+CONFIG_PACKAGE_kmod-fs-xfs=m
+# CONFIG_PACKAGE_kmod-fuse is not set
+CONFIG_PACKAGE_kmod-nls-base=m
+CONFIG_PACKAGE_kmod-nls-cp1250=m
+CONFIG_PACKAGE_kmod-nls-cp437=m
+CONFIG_PACKAGE_kmod-nls-cp850=m
+CONFIG_PACKAGE_kmod-nls-iso8859-1=m
+CONFIG_PACKAGE_kmod-nls-iso8859-15=m
+CONFIG_PACKAGE_kmod-nls-iso8859-2=m
+CONFIG_PACKAGE_kmod-nls-koi8r=m
+CONFIG_PACKAGE_kmod-nls-utf8=m
+# CONFIG_PACKAGE_kmod-shfs is not set
+
+#
+# I2C Bus
+#
+CONFIG_PACKAGE_kmod-i2c-core=m
+CONFIG_PACKAGE_kmod-i2c-algos=m
+
+#
+# Netfilter Extensions
+#
+CONFIG_PACKAGE_kmod-arptables=m
+CONFIG_PACKAGE_kmod-ebtables=m
+CONFIG_PACKAGE_kmod-ip6tables=m
+CONFIG_PACKAGE_kmod-ipt-conntrack=m
+CONFIG_PACKAGE_kmod-ipt-extra=m
+CONFIG_PACKAGE_kmod-ipt-filter=m
+CONFIG_PACKAGE_kmod-ipt-imq=m
+CONFIG_PACKAGE_kmod-ipt-ipopt=m
+CONFIG_PACKAGE_kmod-ipt-iprange=m
+CONFIG_PACKAGE_kmod-ipt-ipsec=m
+CONFIG_PACKAGE_kmod-ipt-ipset=m
+CONFIG_PACKAGE_kmod-ipt-nat=m
+CONFIG_PACKAGE_kmod-ipt-nathelper=y
+CONFIG_PACKAGE_kmod-ipt-nathelper-extra=m
+CONFIG_PACKAGE_kmod-ipt-queue=m
+CONFIG_PACKAGE_kmod-ipt-ulog=m
+
+#
+# Network Devices
+#
+CONFIG_PACKAGE_kmod-3c59x=m
+CONFIG_PACKAGE_kmod-8139too=m
+CONFIG_PACKAGE_kmod-e100=m
+CONFIG_PACKAGE_kmod-e1000=m
+CONFIG_PACKAGE_kmod-natsemi=m
+CONFIG_PACKAGE_kmod-ne2k-pci=m
+CONFIG_PACKAGE_kmod-r8169=m
+CONFIG_PACKAGE_kmod-sis900=m
+CONFIG_PACKAGE_kmod-via-rhine=y
+
+#
+# Network Support
+#
+CONFIG_PACKAGE_kmod-atm=m
+CONFIG_PACKAGE_kmod-atmtcp=m
+CONFIG_PACKAGE_kmod-ax25=m
+CONFIG_PACKAGE_kmod-bonding=m
+CONFIG_PACKAGE_kmod-gre=m
+CONFIG_PACKAGE_kmod-ipsec=m
+CONFIG_PACKAGE_kmod-ipsec4=m
+CONFIG_PACKAGE_kmod-ipsec6=m
+CONFIG_PACKAGE_kmod-iptunnel4=m
+CONFIG_PACKAGE_kmod-ipv6=m
+CONFIG_PACKAGE_kmod-mp-alg=m
+CONFIG_PACKAGE_kmod-ppp=y
+CONFIG_PACKAGE_kmod-mppe=m
+CONFIG_PACKAGE_kmod-pppoa=m
+CONFIG_PACKAGE_kmod-pppoe=y
+CONFIG_PACKAGE_kmod-sched=m
+CONFIG_PACKAGE_kmod-tun=m
+
+#
+# Other modules
+#
+CONFIG_PACKAGE_kmod-bluetooth=m
+CONFIG_PACKAGE_kmod-capi=m
+CONFIG_PACKAGE_kmod-crypto=m
+# CONFIG_PACKAGE_kmod-gspca is not set
+CONFIG_PACKAGE_kmod-hw-crypto=y
+CONFIG_PACKAGE_kmod-hw-rng=y
+CONFIG_PACKAGE_kmod-hwmon=m
+CONFIG_PACKAGE_kmod-hwmon-pc87360=m
+CONFIG_PACKAGE_kmod-ide-aec62xx=m
+CONFIG_PACKAGE_kmod-ide-core=m
+CONFIG_PACKAGE_kmod-ide-pdc202xx=m
+CONFIG_PACKAGE_kmod-input-core=m
+CONFIG_PACKAGE_kmod-input-evdev=m
+CONFIG_PACKAGE_kmod-leds-alix=y
+CONFIG_PACKAGE_kmod-linux-ocf=y
+CONFIG_PACKAGE_kmod-loop=m
+CONFIG_PACKAGE_kmod-lp=m
+CONFIG_PACKAGE_kmod-nbd=m
+CONFIG_PACKAGE_kmod-pcmcia-core=m
+CONFIG_PACKAGE_kmod-pcmcia-serial=m
+CONFIG_PACKAGE_kmod-scsi-core=m
+CONFIG_PACKAGE_kmod-softdog=m
+CONFIG_PACKAGE_kmod-sound-core=m
+CONFIG_PACKAGE_kmod-videodev=m
+# CONFIG_PACKAGE_kmod-spca5xx-le is not set
+
+#
+# USB Support
+#
+CONFIG_PACKAGE_kmod-usb-core=m
+CONFIG_PACKAGE_kmod-cpia2=m
+CONFIG_PACKAGE_kmod-ueagle-atm=m
+CONFIG_PACKAGE_kmod-usb-acm=m
+CONFIG_PACKAGE_kmod-usb-atm=m
+CONFIG_PACKAGE_kmod-usb-audio=m
+CONFIG_PACKAGE_kmod-usb-hid=m
+CONFIG_PACKAGE_kmod-usb-net=m
+CONFIG_PACKAGE_kmod-usb-net-asix=m
+CONFIG_PACKAGE_kmod-usb-net-kaweth=m
+CONFIG_PACKAGE_kmod-usb-net-pegasus=m
+CONFIG_PACKAGE_kmod-usb-ohci=m
+CONFIG_PACKAGE_kmod-usb-printer=m
+CONFIG_PACKAGE_kmod-usb-pwc=m
+# CONFIG_PACKAGE_kmod-usb-qc is not set
+CONFIG_PACKAGE_kmod-usb-serial=m
+CONFIG_PACKAGE_kmod-usb-serial-airprime=m
+CONFIG_PACKAGE_kmod-usb-serial-belkin=m
+CONFIG_PACKAGE_kmod-usb-serial-ftdi=m
+CONFIG_PACKAGE_kmod-usb-serial-mct=m
+CONFIG_PACKAGE_kmod-usb-serial-option=m
+CONFIG_PACKAGE_kmod-usb-serial-pl2303=m
+CONFIG_PACKAGE_kmod-usb-serial-sierrawireless=m
+CONFIG_PACKAGE_kmod-usb-serial-visor=m
+CONFIG_PACKAGE_kmod-usb-speedtouch=m
+CONFIG_PACKAGE_kmod-usb-storage=m
+CONFIG_PACKAGE_kmod-usb-uhci=m
+CONFIG_PACKAGE_kmod-usb-yealink=m
+CONFIG_PACKAGE_kmod-usb2=m
+
+#
+# Wireless Drivers
+#
+CONFIG_PACKAGE_kmod-acx=m
+CONFIG_PACKAGE_kmod-hostap=m
+CONFIG_PACKAGE_kmod-hostap-pci=m
+CONFIG_PACKAGE_kmod-hostap-plx=m
+CONFIG_PACKAGE_kmod-ieee80211=m
+CONFIG_PACKAGE_kmod-ieee80211-softmac=m
+CONFIG_PACKAGE_kmod-mac80211=m
+CONFIG_PACKAGE_kmod-madwifi=y
+CONFIG_PACKAGE_kmod-net-airo=m
+CONFIG_PACKAGE_kmod-net-bcm43xx=m
+CONFIG_PACKAGE_kmod-net-hermes=m
+CONFIG_PACKAGE_kmod-net-hermes-pci=m
+CONFIG_PACKAGE_kmod-net-hermes-plx=m
+CONFIG_PACKAGE_kmod-net-ipw2100=m
+CONFIG_PACKAGE_kmod-net-ipw2200=m
+CONFIG_PACKAGE_kmod-net-prism54=m
+CONFIG_PACKAGE_kmod-net-zd1211rw=m
+CONFIG_PACKAGE_kmod-rt2500=m
+CONFIG_PACKAGE_kmod-rt61=m
+CONFIG_PACKAGE_kmod-zd1211=m
diff -Nur kamikaze_7.09.orig/include/kernel.mk kamikaze_7.09/include/kernel.mk
--- kamikaze_7.09.orig/include/kernel.mk	2007-09-20 10:53:15.000000000 +0200
+++ kamikaze_7.09/include/kernel.mk	2008-06-19 17:34:17.000000000 +0200
@@ -64,7 +64,7 @@
 			for mod in $$$$$$$$2; do \
 				getvar mod; \
 			done \
-		) > $(2)/etc/modules.d/$$$$$$$$1-$(1); \
+		) | sed -e 's|/| |g' > $(2)/etc/modules.d/$$$$$$$$1-$(1); \
 		modules="$$$$$$$${modules:+$$$$$$$$modules }$$$$$$$$1-$(1)"; \
 	}; \
 	$(3) \
diff -Nur kamikaze_7.09.orig/package/cryptotest-bgp/Makefile kamikaze_7.09/package/cryptotest-bgp/Makefile
--- kamikaze_7.09.orig/package/cryptotest-bgp/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/cryptotest-bgp/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,50 @@
+# 
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 8659 2007-09-07 08:34:51Z nico $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=cryptotest-bgp
+PKG_VERSION:=1.10
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/bgp/cryptotest
+
+include $(INCLUDE_DIR)/package.mk
+
+TARGET_CFLAGS+= -I$(LINUX_DIR)/crypto/ocf
+
+define Package/$(PKG_NAME)
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Simple tool for testing hardware/system crypto support.
+endef
+
+define Package/$(PKG_NAME)/description
+  Simple tool for testing hardware/system crypto support.
+
+  http://ocf-linux.sourceforge.net/
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+	$(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+	$(TARGET_CC) $(TARGET_CFLAGS) \
+		-o $(PKG_BUILD_DIR)/cryptotest \
+		$(PKG_BUILD_DIR)/cryptotest.c
+endef
+
+define Package/$(PKG_NAME)/install
+	$(INSTALL_DIR) $(1)/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/cryptotest $(1)/bin/
+endef
+
+$(eval $(call BuildPackage,$(PKG_NAME)))
diff -Nur kamikaze_7.09.orig/package/cryptotest-bgp/src/cryptokeytest.c kamikaze_7.09/package/cryptotest-bgp/src/cryptokeytest.c
--- kamikaze_7.09.orig/package/cryptotest-bgp/src/cryptokeytest.c	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/cryptotest-bgp/src/cryptokeytest.c	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,292 @@
+/* $FreeBSD: src/tools/tools/crypto/cryptokeytest.c,v 1.2 2007/03/21 03:42:51 sam Exp $ */
+/*
+ * The big num stuff is a bit broken at the moment and I've not yet fixed it.
+ * The symtom is that odd size big nums will fail.  Test code below (it only
+ * uses modexp currently).
+ * 
+ * --Jason L. Wright
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <endian.h>
+#include <sys/time.h>
+#include <cryptodev.h>
+#include <openssl/bn.h>
+
+#include <paths.h>
+#include <fcntl.h>
+#include <err.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int	crid = CRYPTO_FLAG_HARDWARE;
+int	verbose = 0;
+static int errs;
+
+static int
+devcrypto(void)
+{
+	static int fd = -1;
+
+	if (fd < 0) {
+		fd = open(_PATH_DEV "crypto", O_RDWR, 0);
+		if (fd < 0)
+			err(1, _PATH_DEV "crypto");
+		if (fcntl(fd, F_SETFD, 1) == -1)
+			err(1, "fcntl(F_SETFD) (devcrypto)");
+	}
+	return fd;
+}
+
+static int
+crlookup(const char *devname)
+{
+	struct crypt_find_op find;
+
+	find.crid = -1;
+	strlcpy(find.name, devname, sizeof(find.name));
+	if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
+		err(1, "ioctl(CIOCFINDDEV)");
+	return find.crid;
+}
+
+static const char *
+crfind(int crid)
+{
+	static struct crypt_find_op find;
+
+	bzero(&find, sizeof(find));
+	find.crid = crid;
+	if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
+		err(1, "ioctl(CIOCFINDDEV)");
+	return find.name;
+}
+
+/*
+ * Convert a little endian byte string in 'p' that
+ * is 'plen' bytes long to a BIGNUM. If 'dst' is NULL,
+ * a new BIGNUM is allocated.  Returns NULL on failure.
+ *
+ * XXX there has got to be a more efficient way to do
+ * this, but I haven't figured out enough of the OpenSSL
+ * magic.
+ */
+BIGNUM *
+le_to_bignum(BIGNUM *dst, u_int8_t *p, int plen)
+{
+	u_int8_t *pd;
+	int i;
+
+	if (plen == 0)
+		return (NULL);
+
+	if ((pd = (u_int8_t *)malloc(plen)) == NULL)
+		return (NULL);
+
+	for (i = 0; i < plen; i++)
+		pd[i] = p[plen - i - 1];
+
+	dst = BN_bin2bn(pd, plen, dst);
+	free(pd);
+	return (dst);
+}
+
+/*
+ * Convert a BIGNUM to a little endian byte string.
+ * If 'rd' is NULL, allocate space for it, otherwise
+ * 'rd' is assumed to have room for BN_num_bytes(n)
+ * bytes.  Returns NULL on failure.
+ */
+u_int8_t *
+bignum_to_le(BIGNUM *n, u_int8_t *rd)
+{
+	int i, j, k;
+	int blen = BN_num_bytes(n);
+
+	if (blen == 0)
+		return (NULL);
+	if (rd == NULL)
+		rd = (u_int8_t *)malloc(blen);
+	if (rd == NULL)
+		return (NULL);
+
+	for (i = 0, j = 0; i < n->top; i++) {
+		for (k = 0; k < BN_BITS2 / 8; k++) {
+			if ((j + k) >= blen)
+				goto out;
+			rd[j + k] = n->d[i] >> (k * 8);
+		}
+		j += BN_BITS2 / 8;
+	}
+out:
+	return (rd);
+}
+
+int
+UB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
+{
+	struct crypt_kop kop;
+	u_int8_t *ale, *ble, *cle;
+	static int crypto_fd = -1;
+
+	if (crypto_fd == -1 && ioctl(devcrypto(), CRIOGET, &crypto_fd) == -1)
+		err(1, "CRIOGET");
+
+	if ((ale = bignum_to_le(a, NULL)) == NULL)
+		err(1, "bignum_to_le, a");
+	if ((ble = bignum_to_le(b, NULL)) == NULL)
+		err(1, "bignum_to_le, b");
+	if ((cle = bignum_to_le(c, NULL)) == NULL)
+		err(1, "bignum_to_le, c");
+
+	bzero(&kop, sizeof(kop));
+	kop.crk_op = CRK_MOD_EXP;
+	kop.crk_iparams = 3;
+	kop.crk_oparams = 1;
+	kop.crk_crid = crid;
+	kop.crk_param[0].crp_p = ale;
+	kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8;
+	kop.crk_param[1].crp_p = ble;
+	kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8;
+	kop.crk_param[2].crp_p = cle;
+	kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8;
+	kop.crk_param[3].crp_p = cle;
+	kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8;
+
+	if (ioctl(crypto_fd, CIOCKEY2, &kop) == -1)
+		warn("CIOCKEY");
+	if (verbose)
+		printf("device = %s\n", crfind(kop.crk_crid));
+
+	bzero(ale, BN_num_bytes(a));
+	free(ale);
+	bzero(ble, BN_num_bytes(b));
+	free(ble);
+
+	if (kop.crk_status != 0) {
+		printf("error %d\n", kop.crk_status);
+		bzero(cle, BN_num_bytes(c));
+		free(cle);
+		return (-1);
+	} else {
+		res = le_to_bignum(res, cle, BN_num_bytes(c));
+		bzero(cle, BN_num_bytes(c));
+		free(cle);
+		if (res == NULL)
+			err(1, "le_to_bignum");
+		return (0);
+	}
+	return (0);
+}
+
+void
+show_result(a, b, c, sw, hw)
+BIGNUM *a, *b, *c, *sw, *hw;
+{
+	printf("\n");
+
+	printf("A = ");
+	BN_print_fp(stdout, a);
+	printf("\n");
+
+	printf("B = ");
+	BN_print_fp(stdout, b);
+	printf("\n");
+
+	printf("C = ");
+	BN_print_fp(stdout, c);
+	printf("\n");
+
+	printf("sw= ");
+	BN_print_fp(stdout, sw);
+	printf("\n");
+
+	printf("hw= ");
+	BN_print_fp(stdout, hw);
+	printf("\n");
+
+	printf("\n");
+}
+
+void
+testit(void)
+{
+	BIGNUM *a, *b, *c, *r1, *r2;
+	BN_CTX *ctx;
+
+	ctx = BN_CTX_new();
+
+	a = BN_new();
+	b = BN_new();
+	c = BN_new();
+	r1 = BN_new();
+	r2 = BN_new();
+
+	BN_pseudo_rand(a, 1023, 0, 0);
+	BN_pseudo_rand(b, 1023, 0, 0);
+	do {
+		BN_pseudo_rand(c, 1024, 0, 0);
+	} while (!BN_is_odd(c));
+	BN_set_bit(c, 1023);
+
+	if (BN_cmp(a, c) > 0) {
+		BIGNUM *rem = BN_new();
+
+		BN_mod(rem, a, c, ctx);
+		UB_mod_exp(r2, rem, b, c, ctx);
+		BN_free(rem);
+	} else {
+		UB_mod_exp(r2, a, b, c, ctx);
+	}
+	BN_mod_exp(r1, a, b, c, ctx);
+
+	if (BN_cmp(r1, r2) != 0) {
+		errs++;
+		show_result(a, b, c, r1, r2);
+	}
+
+	BN_free(r2);
+	BN_free(r1);
+	BN_free(c);
+	BN_free(b);
+	BN_free(a);
+	BN_CTX_free(ctx);
+}
+
+static void
+usage(const char* cmd)
+{
+	printf("usage: %s [-d dev] [-v] [count]\n", cmd);
+	printf("count is the number of bignum ops to do\n");
+	printf("\n");
+	printf("-d use specific device\n");
+	printf("-v be verbose\n");
+	exit(-1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, i;
+
+	while ((c = getopt(argc, argv, "d:v")) != -1) {
+		switch (c) {
+		case 'd':
+			crid = crlookup(optarg);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+	argc -= optind, argv += optind;
+
+	for (i = 0; i < 1000; i++) {
+		fprintf(stderr, "test %d, errs=%d\n", i, errs);
+		testit();
+	}
+	return (0);
+}
diff -Nur kamikaze_7.09.orig/package/cryptotest-bgp/src/cryptotest.c kamikaze_7.09/package/cryptotest-bgp/src/cryptotest.c
--- kamikaze_7.09.orig/package/cryptotest-bgp/src/cryptotest.c	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/cryptotest-bgp/src/cryptotest.c	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,741 @@
+/*-
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD: src/tools/tools/crypto/cryptotest.c,v 1.9 2007/03/21 03:42:51 sam Exp $
+ */
+
+/*
+ * Simple tool for testing hardware/system crypto support.
+ *
+ * cryptotest [-czsbv] [-a algorithm] [count] [size ...]
+ *
+ * Run count iterations of a crypt+decrypt or mac operation on a buffer of
+ * size bytes.  A random key and iv are used.  Options:
+ *	-c	check the results
+ *	-d dev	pin work on device dev
+ *	-z	run all available algorithms on a variety of buffer sizes
+ *	-v	be verbose
+ *	-b	mark operations for batching
+ *	-p	profile kernel crypto operations (must be root)
+ *	-t n	fork n threads and run tests concurrently
+ * Known algorithms are:
+ *	null	null cbc
+ *	des	des cbc
+ *	3des	3des cbc
+ *	blf	blowfish cbc
+ *	cast	cast cbc
+ *	skj	skipjack cbc
+ *	aes	rijndael/aes 128-bit cbc
+ *	aes192	rijndael/aes 192-bit cbc
+ *	aes256	rijndael/aes 256-bit cbc
+ *	md5	md5 hmac
+ *	md5	md5 hmac
+ *	sha1	sha1
+ *	sha1_hmac	sha1 hmac
+ *	sha256	256-bit sha2
+ *	sha256_hmac	256-bit sha2 hmac
+ *	sha384	384-bit sha2
+ *	sha384_hmac	384-bit sha2 hmac
+ *	sha512	512--bit sha2
+ *	sha512_hmac	512--bit sha2 hmac
+ *
+ * For a test of how fast a crypto card is, use something like:
+ *	cryptotest -z 1024
+ * This will run a series of tests using the available crypto/cipher
+ * algorithms over a variety of buffer sizes.  The 1024 says to do 1024
+ * iterations.  Extra arguments can be used to specify one or more buffer
+ * sizes to use in doing tests.
+ *
+ * To fork multiple processes all doing the same work, specify -t X on the
+ * command line to get X "threads" running simultaneously.  No effort is made
+ * to synchronize the threads or otherwise maximize load.
+ *
+ * If the kernel crypto code is built with CRYPTO_TIMING and you run as root,
+ * then you can specify the -p option to get a "profile" of the time spent
+ * processing crypto operations.  At present this data is only meaningful for
+ * symmetric operations.  To get meaningful numbers you must run on an idle
+ * machine.
+ *
+ * Expect ~400 Mb/s for a Broadcom 582x for 8K buffers on a reasonable CPU
+ * (64-bit PCI helps).  Hifn 7811 parts top out at ~110 Mb/s.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <err.h>
+
+#include <string.h>
+#include <err.h>
+
+#include <sys/sysctl.h>
+#include <time.h>
+#include <sys/time.h>
+#include <cryptodev.h>
+
+#define	CHUNK	64	/* how much to display */
+#define	N(a)		(sizeof (a) / sizeof (a[0]))
+#define	streq(a,b)	(strcasecmp(a,b) == 0)
+
+void	hexdump(char *, int);
+
+int	verbose = 0;
+int	opflags = 0;
+int	verify = 0;
+int	crid = CRYPTO_FLAG_HARDWARE | CRYPTO_FLAG_SOFTWARE;
+
+int swap_iv = 0;
+int swap_key = 0;
+int swap_data = 0;
+
+static void swap_buf(char *buf, int len)
+{
+	int i;
+	char tmp[4];
+	for (i = 0; i < len; i += 4) {
+		memcpy(tmp, &buf[i], 4);
+		buf[i + 0] = tmp[3];
+		buf[i + 1] = tmp[2];
+		buf[i + 2] = tmp[1];
+		buf[i + 3] = tmp[0];
+	}
+}
+
+#define MAX_IV_SIZE 16
+
+struct alg {
+	const char* name;
+	int	ishash;
+	int	blocksize;
+	int	minkeylen;
+	int	maxkeylen;
+	int	hashsize;
+	int	code;
+} algorithms[] = {
+#ifdef CRYPTO_NULL_CBC
+	{ "null",			0,	8,	1,	256,	0,	CRYPTO_NULL_CBC },
+#endif
+	{ "des",			0,	8,	8,	8,		0,	CRYPTO_DES_CBC },
+	{ "3des",			0,	8,	24,	24,		0,	CRYPTO_3DES_CBC },
+	{ "blf",			0,	8,	5,	56,		0,	CRYPTO_BLF_CBC },
+	{ "cast",			0,	8,	5,	16,		0,	CRYPTO_CAST_CBC },
+	{ "skj",			0,	8,	10,	10,		0,	CRYPTO_SKIPJACK_CBC },
+	{ "aes",			0,	16,	16,	16,		0,	CRYPTO_RIJNDAEL128_CBC},
+	{ "aes192",			0,	16,	24,	24,		0,	CRYPTO_RIJNDAEL128_CBC},
+	{ "aes256",			0,	16,	32,	32,		0,	CRYPTO_RIJNDAEL128_CBC},
+#ifdef notdef
+	{ "arc4",			0,	8,	1,	32,		0,	CRYPTO_ARC4 },
+#endif
+	{ "md5",			1,	8,	0,	0,		16,	CRYPTO_MD5 },
+	{ "md5_hmac",		1,	8,	1,	64,		16,	CRYPTO_MD5_HMAC },
+	{ "sha1",			1,	8,	0,	0,		20,	CRYPTO_SHA1 },
+	{ "sha1_hmac",		1,	1,	1,	64,		20,	CRYPTO_SHA1_HMAC },
+	{ "sha256",			1,	8,	0,	0,		32,	CRYPTO_SHA2_256 },
+	{ "sha256_hmac",	1,	1,	1,	64,		32,	CRYPTO_SHA2_256_HMAC },
+	{ "sha384",			1,	8,	0,	0,		48,	CRYPTO_SHA2_384 },
+	{ "sha384_hmac",	1,	1,	1,	64,		48,	CRYPTO_SHA2_384_HMAC },
+	{ "sha512",			1,	8,	0,	0,		64,	CRYPTO_SHA2_512 },
+	{ "sha512_hmac",	1,	1,	1,	64,		64,	CRYPTO_SHA2_512_HMAC },
+};
+
+static void
+usage(const char* cmd)
+{
+	printf("usage: %s [-czsbvVKD] [-d dev] [-a algorithm] [count] [size ...]\n",
+		cmd);
+	printf("where algorithm is one of:\n");
+	printf("    des 3des (default) blf (blowfish) cast skj (skipjack)\n");
+	printf("    aes (aka rijndael) aes192 aes256 arc4\n");
+	printf("    md5 md5_hmac sha1 sha1_hmac sha256 sha256_hmac\n");
+	printf("    sha384 sha384_hmac sha512 sha512_hmac\n");
+	printf("count is the number of encrypt/decrypt ops to do\n");
+	printf("size is the number of bytes of text to encrypt+decrypt\n");
+	printf("\n");
+	printf("-c check the results (slows timing)\n");
+	printf("-d use specific device\n");
+	printf("-z run all available algorithms on a variety of sizes\n");
+	printf("-v be verbose\n");
+	printf("-b mark operations for batching\n");
+	printf("-p profile kernel crypto operation (must be root)\n");
+	printf("-V swap IV\n");
+	printf("-K swap KEY\n");
+	printf("-D swap DATA\n");
+	exit(-1);
+}
+
+static struct alg*
+getalgbycode(int cipher)
+{
+	int i;
+
+	for (i = 0; i < N(algorithms); i++)
+		if (cipher == algorithms[i].code)
+			return &algorithms[i];
+	return NULL;
+}
+
+static struct alg*
+getalgbyname(const char* name)
+{
+	int i;
+
+	for (i = 0; i < N(algorithms); i++)
+		if (streq(name, algorithms[i].name))
+			return &algorithms[i];
+	return NULL;
+}
+
+static int
+devcrypto(void)
+{
+	static int fd = -1;
+
+	if (fd < 0) {
+		fd = open(_PATH_DEV "crypto", O_RDWR, 0);
+		if (fd < 0)
+			err(1, _PATH_DEV "crypto");
+		if (fcntl(fd, F_SETFD, 1) == -1)
+			err(1, "fcntl(F_SETFD) (devcrypto)");
+	}
+	return fd;
+}
+
+static int
+crlookup(const char *devname)
+{
+	struct crypt_find_op find;
+
+	find.crid = -1;
+	strlcpy(find.name, devname, sizeof(find.name));
+	if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
+		err(1, "line %d:ioctl(CIOCFINDDEV)", __LINE__);
+	return find.crid;
+}
+
+static const char *
+crfind(int crid)
+{
+	static struct crypt_find_op find;
+
+	bzero(&find, sizeof(find));
+	find.crid = crid;
+	if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1)
+		err(1, "line %d:ioctl(CIOCFINDDEV): crid %d", __LINE__, crid);
+	return find.name;
+}
+
+static int
+crget(void)
+{
+	int fd;
+
+	if (ioctl(devcrypto(), CRIOGET, &fd) == -1)
+		err(1, "line %d:ioctl(CRIOGET)", __LINE__);
+	if (fcntl(fd, F_SETFD, 1) == -1)
+		err(1, "fcntl(F_SETFD) (crget)");
+	return fd;
+}
+
+static char
+rdigit(void)
+{
+#if 1
+	const char a[] = {
+		0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41,
+		0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01
+	};
+	return 0x20+a[random()%N(a)];
+#else
+	static unsigned char c = 0;
+	return (c++);
+#endif
+}
+
+static void
+runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv)
+{
+	int i, fd = crget();
+	struct timeval start, stop;
+	char *cleartext = NULL, *ciphertext = NULL, *originaltext = NULL;
+	struct session2_op sop;
+	struct crypt_op cop;
+	char iv[MAX_IV_SIZE];
+
+	bzero(&sop, sizeof(sop));
+	if (!alg->ishash) {
+		sop.keylen = (alg->minkeylen + alg->maxkeylen)/2;
+		sop.key = (char *) malloc(sop.keylen);
+		if (sop.key == NULL)
+			err(1, "malloc (key)");
+		for (i = 0; i < sop.keylen; i++)
+			sop.key[i] = rdigit();
+		sop.cipher = alg->code;
+		if (swap_key)
+			swap_buf(sop.key, sop.keylen);
+	} else {
+		sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2;
+		sop.mackey = (char *) malloc(sop.mackeylen);
+		if (sop.mackey == NULL)
+			err(1, "malloc (mac)");
+		for (i = 0; i < sop.mackeylen; i++)
+			sop.mackey[i] = rdigit();
+		sop.mac = alg->code;
+		if (swap_key)
+			swap_buf(sop.mackey, sop.mackeylen);
+	}
+	sop.crid = crid;
+	if (verbose)
+		printf(" crid = %x\n", crid);
+	if (ioctl(fd, cmd, &sop) < 0) {
+		if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) {
+			close(fd);
+			if (verbose) {
+				printf("cipher %s", alg->name);
+				if (alg->ishash)
+					printf(" mackeylen %u\n", sop.mackeylen);
+				else {
+					printf(" keylen %u", sop.keylen);
+					printf(" mac %s", sop.mac);
+					printf(" alg->code %d", alg->code);
+					printf(" alg->name %s\n", alg->name);
+				}
+				perror("CIOCGSESSION");
+			}
+			/* hardware doesn't support algorithm; skip it */
+			return;
+		}
+		printf("cipher %s keylen %u mackeylen %u\n",
+			alg->name, sop.keylen, sop.mackeylen);
+		err(1, "CIOCGSESSION");
+	}
+
+	originaltext = (char *)malloc((alg->hashsize ? 2 : 3)*size + alg->hashsize);
+	if (originaltext == NULL)
+		err(1, "malloc (text)");
+	cleartext = originaltext+size;
+	ciphertext = cleartext+size;
+	for (i = 0; i < size; i++)
+		cleartext[i] = rdigit();
+	memcpy(originaltext, cleartext, size);
+	for (i = 0; i < N(iv); i++)
+		iv[i] = rdigit();
+
+	if (verbose) {
+		printf("alg = %s\n", alg->name);
+		printf("session = 0x%x\n", sop.ses);
+		printf("device = %s\n", crfind(sop.crid));
+		printf("count = %d, size = %d\n", count, size);
+		if (!alg->ishash) {
+			printf("iv:");
+			hexdump(iv, sizeof iv);
+		}
+		printf("cleartext:");
+		hexdump(cleartext, MIN(size, CHUNK));
+	}
+
+	gettimeofday(&start, NULL);
+	if (!alg->ishash) {
+		for (i = 0; i < count; i++) {
+			cop.ses = sop.ses;
+			cop.op = COP_ENCRYPT;
+			cop.flags = opflags;
+			cop.len = size;
+			cop.src = cleartext;
+			cop.dst = ciphertext;
+			cop.mac = 0;
+			cop.iv = iv;
+
+			if (swap_data)
+				swap_buf(cleartext, size);
+			if (swap_data)
+				swap_buf(ciphertext, size);
+			if (swap_iv)
+				swap_buf(iv, N(iv));
+
+			if (ioctl(fd, CIOCCRYPT, &cop) < 0)
+				err(1, "line %d:ioctl(CIOCCRYPT)", __LINE__);
+
+			if (swap_data)
+				swap_buf(cleartext, size);
+			if (swap_data)
+				swap_buf(ciphertext, size);
+			if (swap_iv)
+				swap_buf(iv, N(iv));
+
+			if (verify && bcmp(ciphertext, cleartext, size) == 0) {
+				printf("cipher text unchanged:");
+				hexdump(ciphertext, size);
+			}
+
+			if (verbose) {
+				printf("ciphertext:");
+				hexdump(ciphertext, MIN(size, CHUNK));
+				printf("cipheriv:");
+				hexdump(iv, MIN(size, CHUNK));
+			}
+
+			memset(cleartext, 'x', MIN(size, CHUNK));
+			cop.ses = sop.ses;
+			cop.op = COP_DECRYPT;
+			cop.flags = opflags;
+			cop.len = size;
+			cop.src = ciphertext;
+			cop.dst = cleartext;
+			cop.mac = 0;
+			cop.iv = iv;
+
+			if (swap_data)
+				swap_buf(cleartext, size);
+			if (swap_data)
+				swap_buf(ciphertext, size);
+			if (swap_iv)
+				swap_buf(iv, N(iv));
+
+			if (ioctl(fd, CIOCCRYPT, &cop) < 0)
+				err(1, "line %d:ioctl(CIOCCRYPT)", __LINE__);
+
+			if (swap_data)
+				swap_buf(cleartext, size);
+			if (swap_data)
+				swap_buf(ciphertext, size);
+			if (swap_iv)
+				swap_buf(iv, N(iv));
+
+			if (verify && bcmp(cleartext, originaltext, size) != 0) {
+				printf("decrypt mismatch:\n");
+				printf("original:");
+				hexdump(originaltext, size);
+				printf("cleartext:");
+				hexdump(cleartext, size);
+			}
+		}
+	} else {
+		for (i = 0; i < count; i++) {
+			cop.ses = sop.ses;
+			cop.op = 0;
+			cop.flags = opflags;
+			cop.len = size;
+			cop.src = cleartext;
+			cop.dst = 0;
+			cop.mac = ciphertext;
+			cop.iv = 0;
+
+			if (ioctl(fd, CIOCCRYPT, &cop) < 0)
+				err(1, "line %d:ioctl(CIOCCRYPT)", __LINE__);
+
+			if (verbose) {
+				printf("ciphertext:");
+				hexdump(ciphertext, size);
+			}
+		}
+	}
+	gettimeofday(&stop, NULL);
+ 
+	if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
+		perror("ioctl(CIOCFSESSION)");
+
+	if (verbose) {
+		printf("cleartext:");
+		hexdump(cleartext, MIN(size, CHUNK));
+	}
+	timersub(&stop, &start, tv);
+
+	if (sop.key)
+		free(sop.key);
+	if (sop.mackey)
+		free(sop.mackey);
+	free(originaltext);
+
+	close(fd);
+}
+
+#ifdef __FreeBSD__
+static void
+resetstats()
+{
+	struct cryptostats stats;
+	size_t slen;
+
+	slen = sizeof (stats);
+	if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) {
+		perror("kern.crypto_stats");
+		return;
+	}
+	bzero(&stats.cs_invoke, sizeof (stats.cs_invoke));
+	bzero(&stats.cs_done, sizeof (stats.cs_done));
+	bzero(&stats.cs_cb, sizeof (stats.cs_cb));
+	bzero(&stats.cs_finis, sizeof (stats.cs_finis));
+	stats.cs_invoke.min.tv_sec = 10000;
+	stats.cs_done.min.tv_sec = 10000;
+	stats.cs_cb.min.tv_sec = 10000;
+	stats.cs_finis.min.tv_sec = 10000;
+	if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0)
+		perror("kern.cryptostats");
+}
+
+static void
+printt(const char* tag, struct cryptotstat *ts)
+{
+	uint64_t avg, min, max;
+
+	if (ts->count == 0)
+		return;
+	avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count;
+	min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec;
+	max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec;
+	printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n",
+		tag, avg, min, max, ts->count);
+}
+#endif
+
+static void
+runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int profile)
+{
+	int i, status;
+	double t;
+	void *region;
+	struct timeval *tvp;
+#ifdef __FreeBSD__
+	int otiming;
+#endif
+
+	if (size % alg->blocksize) {
+		if (verbose)
+			printf("skipping blocksize %u 'cuz not a multiple of "
+				"%s blocksize %u\n",
+				size, alg->name, alg->blocksize);
+		return;
+	}
+
+	region = mmap(NULL, threads * sizeof (struct timeval),
+			PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
+	if (region == MAP_FAILED) {
+		perror("mmap");
+		return;
+	}
+	tvp = (struct timeval *) region;
+#ifdef __FreeBSD__
+	if (profile) {
+		size_t tlen = sizeof (otiming);
+		int timing = 1;
+
+		resetstats();
+		if (sysctlbyname("debug.crypto_timing", &otiming, &tlen,
+				&timing, sizeof (timing)) < 0)
+			perror("debug.crypto_timing");
+	}
+#endif
+
+	if (threads > 1) {
+		for (i = 0; i < threads; i++)
+			if (fork() == 0) {
+				runtest(alg, count, size, cmd, &tvp[i]);
+				exit(0);
+			}
+		while (waitpid(WAIT_MYPGRP, &status, 0) != -1)
+			;
+	} else
+		runtest(alg, count, size, cmd, tvp);
+
+	t = 0;
+	for (i = 0; i < threads; i++)
+		t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000);
+	if (t) {
+		int nops = alg->ishash ? count : 2*count;
+
+#if 0
+		t /= threads;
+		printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf bytes/sec, %7.1lf Mbit/sec\n",
+		    t, nops, alg->name, size, (double)nops*size / t,
+		    (double)nops*size / t * 8 / 1024 / 1024);
+#else
+		nops *= threads;
+		printf("%8.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n",
+		    t, nops, alg->name, size, (double)nops*size / t,
+		    (double)nops*size / t * 8 / 1024 / 1024);
+#endif
+	}
+#ifdef __FreeBSD__
+	if (profile) {
+		struct cryptostats stats;
+		size_t slen = sizeof (stats);
+
+		if (sysctlbyname("debug.crypto_timing", NULL, NULL,
+				&otiming, sizeof (otiming)) < 0)
+			perror("debug.crypto_timing");
+		if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0)
+			perror("kern.cryptostats");
+		if (stats.cs_invoke.count) {
+			printt("dispatch->invoke", &stats.cs_invoke);
+			printt("invoke->done", &stats.cs_done);
+			printt("done->cb", &stats.cs_cb);
+			printt("cb->finis", &stats.cs_finis);
+		}
+	}
+#endif
+	if (munmap(region, threads * sizeof (struct timeval)) != 0)
+		perror("munmap");
+
+	fflush(stdout);
+}
+
+int
+main(int argc, char **argv)
+{
+	struct alg *alg = NULL;
+	int count = 1;
+	int sizes[128], nsizes = 0;
+	u_long cmd = CIOCGSESSION2;
+	int testall = 0;
+	int maxthreads = 1;
+	int profile = 0;
+	int i, ch;
+
+	srandom(time(0));
+
+	while ((ch = getopt(argc, argv, "cpzsva:bd:t:S:VKD")) != -1) {
+		switch (ch) {
+		case 'V': swap_iv = 1; break;
+		case 'K': swap_key = 1; break;
+		case 'D': swap_data = 1; break;
+#ifdef CIOCGSSESSION
+		case 's':
+			cmd = CIOCGSSESSION;
+			break;
+#endif
+		case 'v':
+			verbose++;
+			break;
+		case 'a':
+			alg = getalgbyname(optarg);
+			if (alg == NULL) {
+				if (streq(optarg, "rijndael"))
+					alg = getalgbyname("aes");
+				else
+					usage(argv[0]);
+			}
+			break;
+		case 'S':
+			srandom(atoi(optarg));
+			break;
+		case 'd':
+			crid = crlookup(optarg);
+			break;
+		case 't':
+			maxthreads = atoi(optarg);
+			break;
+		case 'z':
+			testall = 1;
+			break;
+		case 'p':
+			profile = 1;
+			break;
+		case 'b':
+			opflags |= COP_F_BATCH;
+			break;
+		case 'c':
+			verify = 1;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+	argc -= optind, argv += optind;
+	if (argc > 0)
+		count = atoi(argv[0]);
+	while (argc > 1) {
+		int s = atoi(argv[1]);
+		if (nsizes < N(sizes)) {
+			sizes[nsizes++] = s;
+		} else {
+			printf("Too many sizes, ignoring %u\n", s);
+		}
+		argc--, argv++;
+	}
+	if (nsizes == 0) {
+		if (alg)
+			sizes[nsizes++] = alg->blocksize;
+		else
+			sizes[nsizes++] = 8;
+		if (testall) {
+			/*
+			 * OCF is limited to CRYPTO_MAX_DATA_LEN, so make it 256 bytes less
+			 * for safety sakes.
+			 */
+			while (sizes[nsizes-1] < (CRYPTO_MAX_DATA_LEN - 256)) {
+				sizes[nsizes] = sizes[nsizes-1]<<1;
+				if (sizes[nsizes] > CRYPTO_MAX_DATA_LEN)
+					sizes[nsizes] -= 256;
+				nsizes++;
+			}
+		}
+	}
+
+	if (testall) {
+		for (i = 0; i < N(algorithms); i++) {
+			int j;
+			alg = &algorithms[i];
+			for (j = 0; j < nsizes; j++)
+				runtests(alg, count, sizes[j], cmd, maxthreads, profile);
+		}
+	} else {
+		if (alg == NULL)
+			alg = getalgbycode(CRYPTO_3DES_CBC);
+		for (i = 0; i < nsizes; i++)
+			runtests(alg, count, sizes[i], cmd, maxthreads, profile);
+	}
+
+	return (0);
+}
+
+void
+hexdump(char *p, int n)
+{
+	int i, off;
+
+	for (off = 0; n > 0; off += 16, n -= 16) {
+		printf("%s%04x:", off == 0 ? "\n" : "", off);
+		i = (n >= 16 ? 16 : n);
+		do {
+			printf(" %02x", *p++ & 0xff);
+		} while (--i);
+		printf("\n");
+	}
+}
diff -Nur kamikaze_7.09.orig/package/cryptotest-bgp/src/Makefile kamikaze_7.09/package/cryptotest-bgp/src/Makefile
--- kamikaze_7.09.orig/package/cryptotest-bgp/src/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/cryptotest-bgp/src/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,42 @@
+#	$FreeBSD: src/tools/tools/crypto/Makefile,v 1.8 2004/09/07 18:35:00 sam Exp $
+#
+# Copyright (c) 2002, 2003	Sam Leffler, Errno Consulting
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+ALL=	cryptotest cryptokeytest
+
+all:	${ALL}
+
+# program to test asymmetric crypto functions
+cryptokeytest: cryptokeytest.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o cryptokeytest cryptokeytest.c -lcrypto $(LDLIBS)
+
+clean:
+	rm -f *.o ${ALL} core a.out
+
+romfs:
+	$(ROMFSINST) -e CONFIG_USER_CRYPTO_TOOLS_CRYPTOTEST /bin/cryptotest
+	$(ROMFSINST) -e CONFIG_USER_CRYPTO_TOOLS_CRYPTOKEYTEST /bin/cryptokeytest
+
diff -Nur kamikaze_7.09.orig/package/cryptotest-bgp/src/README kamikaze_7.09/package/cryptotest-bgp/src/README
--- kamikaze_7.09.orig/package/cryptotest-bgp/src/README	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/cryptotest-bgp/src/README	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,44 @@
+$FreeBSD: src/tools/tools/crypto/README,v 1.1 2002/12/14 06:23:58 sam Exp $
+
+The cryptotest program repeatedly encrypts and decrypts a buffer
+with the built-in iv and key, using hardware crypto.  At the end,
+it computes the data rate achieved.  Operations are carried out by
+making ioctl calls to /dev/crypto.
+
+For a test of how fast a crypto card is, use something like:
+
+	cryptotest -z 1024
+
+This will run a series of tests using the available crypto/cipher
+algorithms over a variety of buffer sizes.  The 1024 says to do
+1024 iterations.  Extra arguments can be used to specify one or
+more buffer sizes to use in doing tests.
+
+A sample run is:
+
+ 0.129 sec,    2048    des crypts,       8 bytes,   127120 byte/sec,     1.0 Mb/sec
+ 0.129 sec,    2048    des crypts,      16 bytes,   253915 byte/sec,     1.9 Mb/sec
+ 0.129 sec,    2048    des crypts,      32 bytes,   508942 byte/sec,     3.9 Mb/sec
+ 0.128 sec,    2048    des crypts,      64 bytes,  1020135 byte/sec,     7.8 Mb/sec
+ 0.134 sec,    2048    des crypts,     128 bytes,  1954869 byte/sec,    14.9 Mb/sec
+ 0.142 sec,    2048    des crypts,     256 bytes,  3698107 byte/sec,    28.2 Mb/sec
+ 0.190 sec,    2048    des crypts,    1024 bytes, 11037700 byte/sec,    84.2 Mb/sec
+ 0.264 sec,    2048    des crypts,    2048 bytes, 15891127 byte/sec,   121.2 Mb/sec
+ 0.403 sec,    2048    des crypts,    4096 bytes, 20828998 byte/sec,   158.9 Mb/sec
+ 0.687 sec,    2048    des crypts,    8192 bytes, 24426602 byte/sec,   186.4 Mb/sec
+ 0.129 sec,    2048   3des crypts,       8 bytes,   127321 byte/sec,     1.0 Mb/sec
+ 0.131 sec,    2048   3des crypts,      16 bytes,   249773 byte/sec,     1.9 Mb/sec
+ 0.128 sec,    2048   3des crypts,      32 bytes,   512304 byte/sec,     3.9 Mb/sec
+ 0.128 sec,    2048   3des crypts,      64 bytes,  1021685 byte/sec,     7.8 Mb/sec
+ 0.132 sec,    2048   3des crypts,     128 bytes,  1986511 byte/sec,    15.2 Mb/sec
+ 0.142 sec,    2048   3des crypts,     256 bytes,  3695005 byte/sec,    28.2 Mb/sec
+ 0.190 sec,    2048   3des crypts,    1024 bytes, 11024876 byte/sec,    84.1 Mb/sec
+ 0.264 sec,    2048   3des crypts,    2048 bytes, 15887997 byte/sec,   121.2 Mb/sec
+ 0.402 sec,    2048   3des crypts,    4096 bytes, 20850846 byte/sec,   159.1 Mb/sec
+ 0.689 sec,    2048   3des crypts,    8192 bytes, 24333532 byte/sec,   185.7 Mb/sec
+
+Expect ~400 Mb/s for a Broadcom 582x for 16K buffers on a reasonable
+CPU.  Hifn 7811 parts top out at ~120 Mb/s.  Performance depends
+heavily on memory and bus performance.
+
+This code originally came from openbsd; give them all the credit.
diff -Nur kamikaze_7.09.orig/package/iptraf/Makefile kamikaze_7.09/package/iptraf/Makefile
--- kamikaze_7.09.orig/package/iptraf/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/iptraf/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 9349 2007-10-18 18:46:37Z blogic $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=iptraf
+PKG_VERSION:=3.0.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://iptraf.seul.org/pub/iptraf/ \
+	ftp://the.wiretapped.net/pub/security/network-monitoring/iptraf/
+PKG_MD5SUM:=377371c28ee3c21a76f7024920649ea8
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/iptraf
+  SECTION:=net
+  CATEGORY:=Network
+  DEPENDS:=+libncurses
+  TITLE:=A console-based network monitoring program
+  URL:=http://iptraf.seul.org/
+endef
+
+define Package/iptraf/description
+	IPTraf is a console-based network statistics utility for Linux. It gathers 
+	a variety of figures such as TCP connection packet and byte counts, 
+	interface statistics and activity indicators, TCP/UDP traffic breakdowns, 
+	and LAN station packet and byte counts.
+endef
+
+define Build/Compile	
+	$(MAKE) -C $(PKG_BUILD_DIR)/src \
+		$(TARGET_CONFIGURE_OPTS) \
+		CFLAGS="$(TARGET_CFLAGS)" \
+		DEBUG="" \
+		INCLUDEDIR="-I../support -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
+		LDOPTS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+		PLATFORM="-DPLATFORM=\\\"Linux/$(ARCH)\\\"" \
+		TARGET="/usr/bin" \
+		WORKDIR="/var/lib/iptraf" \
+		all
+endef
+
+define Package/iptraf/install	
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/iptraf $(1)/usr/bin/
+	$(INSTALL_DIR) $(1)/var/lib/iptraf/
+	echo "$(PKG_VERSION)" > $(1)/var/lib/iptraf/version
+	$(INSTALL_DIR) $(1)/var/log/iptraf $(1)/var/run/iptraf
+endef
+
+$(eval $(call BuildPackage,iptraf))
diff -Nur kamikaze_7.09.orig/package/iptraf/patches/001-cross_compile.patch kamikaze_7.09/package/iptraf/patches/001-cross_compile.patch
--- kamikaze_7.09.orig/package/iptraf/patches/001-cross_compile.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/iptraf/patches/001-cross_compile.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,24 @@
+diff -urN iptraf-3.0.0/support/Makefile iptraf-3.0.0.new/support/Makefile
+--- iptraf-3.0.0/support/Makefile	2002-07-19 18:31:48.000000000 +0200
++++ iptraf-3.0.0.new/support/Makefile	2006-04-16 16:07:58.000000000 +0200
+@@ -3,16 +3,14 @@
+ OBJS			= input.o menurt.o listbox.o winops.o labels.o \
+ 				msgboxes.o txbox.o
+ 
+-all: libtextbox.a
+-
+ libtextbox.a: $(OBJS)
+ 	rm -rf libtextbox.a
+-	ar cq libtextbox.a $(OBJS)
+-	ranlib libtextbox.a
+-#	gcc -shared -o libtextbox.so $(OBJS)
++	$(AR) cq libtextbox.a $(OBJS)
++	$(RANLIB) libtextbox.a
++#	$(CC) -shared -o libtextbox.so $(OBJS)
+ 
+ %.o: %.c *.h
+-	gcc -O2 -g -Wall -fPIC $(INCLUDEDIR) -c -o $*.o $<
++	$(CC) $(CFLAGS) -Wall -fPIC $(INCLUDEDIR) -c -o $*.o $<
+ 
+ clean:
+ 	rm -rf *.o *~ libtextbox.a libtextbox.so
diff -Nur kamikaze_7.09.orig/package/iptraf/patches/002-ifaces.patch kamikaze_7.09/package/iptraf/patches/002-ifaces.patch
--- kamikaze_7.09.orig/package/iptraf/patches/002-ifaces.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/iptraf/patches/002-ifaces.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,294 @@
+diff -urN iptraf-3.0.0/src/dirs.h iptraf-3.0.0.new/src/dirs.h
+--- iptraf-3.0.0/src/dirs.h	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/dirs.h	2006-04-16 16:08:27.000000000 +0200
+@@ -155,7 +155,6 @@
+  */
+ 
+ #define ETHFILE		get_path(T_WORKDIR, "ethernet.desc")
+-#define FDDIFILE	get_path(T_WORKDIR, "fddi.desc")
+ 
+ /*
+  * The rvnamed program file
+diff -urN iptraf-3.0.0/src/hostmon.c iptraf-3.0.0.new/src/hostmon.c
+--- iptraf-3.0.0/src/hostmon.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/hostmon.c	2006-04-16 16:29:27.000000000 +0200
+@@ -30,7 +30,6 @@
+ #include <netinet/in.h>
+ #include <linux/if_packet.h>
+ #include <linux/if_ether.h>
+-#include <linux/if_fddi.h>
+ #include <linux/if_tr.h>
+ #include <net/if_arp.h>
+ #include <stdlib.h>
+@@ -293,8 +292,6 @@
+             wprintw(table->tabwin, "Ethernet");
+         else if (entry->un.desc.linktype == LINK_PLIP)
+             wprintw(table->tabwin, "PLIP");
+-        else if (entry->un.desc.linktype == LINK_FDDI)
+-            wprintw(table->tabwin, "FDDI");
+ 
+         wprintw(table->tabwin, " HW addr: %s", entry->un.desc.ascaddr);
+ 
+@@ -722,7 +719,7 @@
+     unsigned long long updtime_usec = 0;
+ 
+     struct desclist elist;      /* Ethernet description list */
+-    struct desclist flist;      /* FDDI description list */
++    struct desclist flist;	/* Other links description list */
+     struct desclist *list = NULL;
+ 
+     FILE *logfile = NULL;
+@@ -786,7 +783,6 @@
+ 
+     initethtab(&table, options->actmode);
+     loaddesclist(&elist, LINK_ETHERNET, WITHETCETHERS);
+-    loaddesclist(&flist, LINK_FDDI, WITHETCETHERS);
+ 
+     if (logging) {
+         if (strcmp(current_logfile, "") == 0) {
+@@ -900,9 +896,7 @@
+             if (pkt_result != PACKET_OK)
+                 continue;
+ 
+-            if ((linktype == LINK_ETHERNET) || (linktype == LINK_FDDI)
+-                || (linktype == LINK_PLIP) || (linktype == LINK_TR) ||
+-                (linktype == LINK_VLAN)) {
++            if ((linktype == LINK_ETHERNET) || (linktype == LINK_PLIP) || (linktype == LINK_TR) || (linktype == LINK_VLAN)) {
+ 
+                 if (fromaddr.sll_protocol == htons(ETH_P_IP))
+                     is_ip = 1;
+@@ -920,12 +914,6 @@
+                     memcpy(scratch_daddr, ((struct ethhdr *) buf)->h_dest,
+                            ETH_ALEN);
+                     list = &elist;
+-                } else if (linktype == LINK_FDDI) {
+-                    memcpy(scratch_saddr, ((struct fddihdr *) buf)->saddr,
+-                           FDDI_K_ALEN);
+-                    memcpy(scratch_daddr, ((struct fddihdr *) buf)->daddr,
+-                           FDDI_K_ALEN);
+-                    list = &flist;
+                 } else if (linktype == LINK_TR) {
+                     memcpy(scratch_saddr, ((struct trh_hdr *) buf)->saddr,
+                            TR_ALEN);
+diff -urN iptraf-3.0.0/src/ifaces.c iptraf-3.0.0.new/src/ifaces.c
+--- iptraf-3.0.0/src/ifaces.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/ifaces.c	2006-04-16 16:10:10.000000000 +0200
+@@ -37,7 +37,7 @@
+ extern int daemonized;
+ 
+ char ifaces[][6] =
+-    { "lo", "eth", "sl", "ppp", "ippp", "plip", "fddi", "isdn", "dvb",
++    { "lo", "eth", "sl", "ppp", "ippp", "plip", "isdn", "dvb",
+     "pvc", "hdlc", "ipsec", "sbni", "tr", "wvlan", "wlan", "sm2", "sm3",
+     "pent", "lec", "brg", "tun", "tap", "cipcb", "tunl", "vlan"
+ };
+diff -urN iptraf-3.0.0/src/landesc.c iptraf-3.0.0.new/src/landesc.c
+--- iptraf-3.0.0/src/landesc.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/landesc.c	2006-04-16 16:10:29.000000000 +0200
+@@ -83,8 +83,6 @@
+ 
+     if (linktype == LINK_ETHERNET)
+         fd = fopen(ETHFILE, "r");
+-    else if (linktype == LINK_FDDI)
+-        fd = fopen(FDDIFILE, "r");
+ 
+     if (fd == NULL) {
+         return;
+@@ -205,8 +203,6 @@
+ 
+     if (linktype == LINK_ETHERNET)
+         fd = fopen(ETHFILE, "w");
+-    else if (linktype == LINK_FDDI)
+-        fd = fopen(FDDIFILE, "w");
+ 
+     if (fd < 0) {
+         etherr();
+diff -urN iptraf-3.0.0/src/links.h iptraf-3.0.0.new/src/links.h
+--- iptraf-3.0.0/src/links.h	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/links.h	2006-04-16 16:10:39.000000000 +0200
+@@ -6,7 +6,6 @@
+ #define LINK_ISDN_RAWIP		6
+ #define LINK_ISDN_CISCOHDLC	7
+ #define LINK_CISCOHDLC  7
+-#define LINK_FDDI		8
+ #define LINK_FRAD		9
+ #define LINK_DLCI		10
+ #define LINK_TR			11
+diff -urN iptraf-3.0.0/src/log.c iptraf-3.0.0.new/src/log.c
+--- iptraf-3.0.0/src/log.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/log.c	2006-04-16 16:10:53.000000000 +0200
+@@ -491,8 +491,6 @@
+                         ptmp->un.desc.ascaddr);
+             else if (ptmp->un.desc.linktype == LINK_PLIP)
+                 fprintf(fd, "\nPLIP address: %s", ptmp->un.desc.ascaddr);
+-            else if (ptmp->un.desc.linktype == LINK_FDDI)
+-                fprintf(fd, "\nFDDI address: %s", ptmp->un.desc.ascaddr);
+ 
+             if (ptmp->un.desc.withdesc)
+                 fprintf(fd, " (%s)", ptmp->un.desc.desc);
+diff -urN iptraf-3.0.0/src/options.c iptraf-3.0.0.new/src/options.c
+--- iptraf-3.0.0/src/options.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/options.c	2006-04-16 16:23:52.000000000 +0200
+@@ -68,8 +68,6 @@
+     tx_additem(menu, NULL, NULL);
+     tx_additem(menu, " ^E^thernet/PLIP host descriptions...",
+                "Manages descriptions for Ethernet and PLIP addresses");
+-    tx_additem(menu, " ^F^DDI/Token Ring host descriptions...",
+-               "Manages descriptions for FDDI and FDDI addresses");
+     tx_additem(menu, NULL, NULL);
+     tx_additem(menu, " E^x^it configuration", "Returns to main menu");
+ }
+@@ -371,9 +369,6 @@
+         case 14:
+             ethdescmgr(LINK_ETHERNET);
+             break;
+-        case 15:
+-            ethdescmgr(LINK_FDDI);
+-            break;
+         }
+ 
+         indicatesetting(row, options, statwin);
+diff -urN iptraf-3.0.0/src/othptab.c iptraf-3.0.0.new/src/othptab.c
+--- iptraf-3.0.0/src/othptab.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/othptab.c	2006-04-16 16:24:21.000000000 +0200
+@@ -19,7 +19,6 @@
+ #include <asm/types.h>
+ #include <linux/if_ether.h>
+ #include <linux/if_tr.h>
+-#include <linux/if_fddi.h>
+ #include <winops.h>
+ #include "arphdr.h"
+ #include "options.h"
+@@ -139,11 +138,6 @@
+                         new_entry->smacaddr);
+             convmacaddr(((struct ethhdr *) packet)->h_dest,
+                         new_entry->dmacaddr);
+-        } else if (linkproto == LINK_FDDI) {
+-            convmacaddr(((struct fddihdr *) packet)->saddr,
+-                        new_entry->smacaddr);
+-            convmacaddr(((struct fddihdr *) packet)->daddr,
+-                        new_entry->dmacaddr);
+         } else if (linkproto == LINK_TR) {
+             convmacaddr(((struct trh_hdr *) packet)->saddr,
+                         new_entry->smacaddr);
+@@ -373,8 +367,7 @@
+         strcat(msgstring, scratchpad);
+ 
+         if ((entry->linkproto == LINK_ETHERNET) ||
+-            (entry->linkproto == LINK_PLIP) ||
+-            (entry->linkproto == LINK_FDDI)) {
++            (entry->linkproto == LINK_PLIP)) {
+             sprintf(scratchpad, " from %s to %s on %s",
+                     entry->smacaddr, entry->dmacaddr, entry->iface);
+ 
+diff -urN iptraf-3.0.0/src/packet.c iptraf-3.0.0.new/src/packet.c
+--- iptraf-3.0.0/src/packet.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/packet.c	2006-04-16 16:11:55.000000000 +0200
+@@ -35,7 +35,6 @@
+ #include <sys/ioctl.h>
+ #include <linux/if_packet.h>
+ #include <linux/if_ether.h>
+-#include <linux/if_fddi.h>
+ #include <linux/if_tr.h>
+ #include <linux/isdn.h>
+ #include <linux/sockios.h>
+@@ -81,8 +80,6 @@
+             result = LINK_ETHERNET;
+         else if (strncmp(ifname, "plip", 4) == 0)
+             result = LINK_PLIP;
+-        else if (strncmp(ifname, "fddi", 4) == 0)       /* For some Ethernet- */
+-            result = LINK_ETHERNET;     /* emulated FDDI ifaces */
+         else if (strncmp(ifname, "dvb", 3) == 0)
+             result = LINK_ETHERNET;
+         else if (strncmp(ifname, "sbni", 4) == 0)
+@@ -136,9 +133,6 @@
+     case ARPHRD_PPP:
+         result = LINK_PPP;
+         break;
+-    case ARPHRD_FDDI:
+-        result = LINK_FDDI;
+-        break;
+     case ARPHRD_IEEE802:
+     case ARPHRD_IEEE802_TR:
+         result = LINK_TR;
+@@ -194,19 +188,6 @@
+         *packet = tpacket + 4;
+         *readlen -= 4;
+         break;
+-    case LINK_FDDI:
+-        *packet = tpacket + sizeof(struct fddihdr);
+-        *readlen -= sizeof(struct fddihdr);
+-
+-        /*
+-         * Move IP data into an aligned buffer.  96 bytes should be sufficient
+-         * for IP and TCP headers with reasonable numbers of options and some
+-         * data.
+-         */
+-
+-        memmove(aligned_buf, *packet, min(SNAPSHOT_LEN, *readlen));
+-        *packet = aligned_buf;
+-        break;
+     case LINK_TR:
+         /*
+          * Token Ring patch supplied by Tomas Dvorak 
+diff -urN iptraf-3.0.0/src/promisc.c iptraf-3.0.0.new/src/promisc.c
+--- iptraf-3.0.0/src/promisc.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/promisc.c	2006-04-16 16:12:56.000000000 +0200
+@@ -81,8 +81,8 @@
+              */
+ 
+             if ((strncmp(buf, "eth", 3) == 0) ||
+-                (strncmp(buf, "fddi", 4) == 0) ||
+                 (strncmp(buf, "tr", 2) == 0) ||
++		(strncmp(buf, "vlan", 4) == 0) ||
+                 (strncmp(ptmp->params.ifname, "wvlan", 4) == 0) ||
+                 (strncmp(ptmp->params.ifname, "lec", 3) == 0) ||
+                 (accept_unsupported_interfaces)) {
+@@ -195,7 +195,7 @@
+ 
+     while (ptmp != NULL) {
+         if (((strncmp(ptmp->params.ifname, "eth", 3) == 0) ||
+-             (strncmp(ptmp->params.ifname, "fddi", 4) == 0) ||
++             (strncmp(ptmp->params.ifname, "vlan", 4) == 0) ||
+              (strncmp(ptmp->params.ifname, "tr", 2) == 0) ||
+              (strncmp(ptmp->params.ifname, "wvlan", 4) == 0) ||
+              (strncmp(ptmp->params.ifname, "lec", 3) == 0)) &&
+diff -urN iptraf-3.0.0/src/rvnamed.h iptraf-3.0.0.new/src/rvnamed.h
+--- iptraf-3.0.0/src/rvnamed.h	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/rvnamed.h	2006-04-16 16:13:39.000000000 +0200
+@@ -1,9 +1,9 @@
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ 
+-#define CHILDSOCKNAME "/dev/rvndcldcomsk"
+-#define PARENTSOCKNAME "/dev/rvndpntcomsk"
+-#define IPTSOCKNAME "/dev/rvndiptcomsk"
++#define CHILDSOCKNAME "/tmp/rvndcldcomsk"
++#define PARENTSOCKNAME "/tmp/rvndpntcomsk"
++#define IPTSOCKNAME "/tmp/rvndiptcomsk"
+ 
+ #define SOCKET_PREFIX	"isock"
+ 
+diff -urN iptraf-3.0.0/src/tcptable.c iptraf-3.0.0.new/src/tcptable.c
+--- iptraf-3.0.0/src/tcptable.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/tcptable.c	2006-04-16 16:13:54.000000000 +0200
+@@ -600,8 +600,6 @@
+ 
+         if ((linkproto == LINK_ETHERNET) || (linkproto == LINK_PLIP)) {
+             convmacaddr(((struct ethhdr *) packet)->h_source, newmacaddr);
+-        } else if (linkproto == LINK_FDDI) {
+-            convmacaddr(((struct fddihdr *) packet)->saddr, newmacaddr);
+         } else if (linkproto == LINK_TR) {
+             convmacaddr(((struct trh_hdr *) packet)->saddr, newmacaddr);
+         }
+diff -urN iptraf-3.0.0/src/tcptable.h iptraf-3.0.0.new/src/tcptable.h
+--- iptraf-3.0.0/src/tcptable.h	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/tcptable.h	2006-04-16 16:14:03.000000000 +0200
+@@ -22,7 +22,6 @@
+ #include <asm/types.h>
+ #include <linux/if_packet.h>
+ #include <linux/if_ether.h>
+-#include <linux/if_fddi.h>
+ #include <linux/if_tr.h>
+ #include <net/if.h>
+ #include <netinet/ip.h>
diff -Nur kamikaze_7.09.orig/package/iptraf/patches/003-exit_menu.patch kamikaze_7.09/package/iptraf/patches/003-exit_menu.patch
--- kamikaze_7.09.orig/package/iptraf/patches/003-exit_menu.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/iptraf/patches/003-exit_menu.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,12 @@
+diff -urN iptraf-3.0.0/src/options.c iptraf-3.0.0.new/src/options.c
+--- iptraf-3.0.0/src/options.c	2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0.new/src/options.c	2007-03-23 13:31:37.000000000 +0100
+@@ -377,7 +377,7 @@
+         }
+ 
+         indicatesetting(row, options, statwin);
+-    } while (row != 17);
++    } while (row != 16);
+ 
+     tx_destroymenu(&menu);
+     del_panel(statpanel);
diff -Nur kamikaze_7.09.orig/package/kernel/modules/other.mk kamikaze_7.09/package/kernel/modules/other.mk
--- kamikaze_7.09.orig/package/kernel/modules/other.mk	2007-09-22 15:50:44.000000000 +0200
+++ kamikaze_7.09/package/kernel/modules/other.mk	2008-06-19 17:34:17.000000000 +0200
@@ -85,6 +85,64 @@
 endef
 $(eval $(call KernelPackage,scsi-core))
 
+define KernelPackage/hw-rng
+  SUBMENU:=$(EMENU)
+  TITLE:=Geode Random Number Generator
+  DEPENDS:=@LINUX_2_6
+  KCONFIG:= \
+	$(CONFIG_HW_RANDOM_GEODE) \
+	$(CONFIG_HW_RANDOM_VIA)
+  FILES:= \
+	$(LINUX_DIR)/drivers/char/hw_random/geode-rng.$(LINUX_KMOD_SUFFIX) \
+	$(LINUX_DIR)/drivers/char/hw_random/via-rng.$(LINUX_KMOD_SUFFIX)
+  AUTOLOAD:=$(call AutoLoad,15,geode-rng via-rng)
+endef
+
+$(eval $(call KernelPackage,hw-rng))
+
+
+define KernelPackage/hw-crypto
+  SUBMENU:=$(EMENU)
+  TITLE:=Geode AES/Padlock Encryption Engine
+  DEPENDS:=@LINUX_2_6
+  KCONFIG:= \
+	$(CONFIG_CRYPTO_HW) \
+	$(CONFIG_CRYPTO_DEV_GEODE)
+  FILES:= \
+	$(LINUX_DIR)/drivers/crypto/geode-aes.$(LINUX_KMOD_SUFFIX) 
+  AUTOLOAD:=$(call AutoLoad,15,geode-aes)
+endef
+
+$(eval $(call KernelPackage,hw-crypto))
+
+
+define KernelPackage/linux-ocf
+  SUBMENU:=$(EMENU)
+  TITLE:=Linux OCF (OpenBSD Crypto Framework) Modules
+  DEPENDS:=@LINUX_2_6
+  KCONFIG:= \
+	$(CONFIG_OCF_OCF) \
+	$(CONFIG_OCF_CRYPTODEV) \
+	$(CONFIG_OCF_CRYPTOSOFT) \
+	$(CONFIG_OCF_RANDOMHARVEST) \
+	$(CONFIG_OCF_FIPS) \
+	$(CONFIG_OCF_SAFE) \
+	$(CONFIG_OCF_IXP4XX) \
+	$(CONFIG_OCF_HIFN) \
+	$(CONFIG_OCF_HIFNHIPP) \
+	$(CONFIG_OCF_TALITOS) \
+	$(CONFIG_OCF_OCFNULL) \
+	$(CONFIG_OCF_BENCH)
+  FILES:= \
+	$(LINUX_DIR)/crypto/ocf/ocf.$(LINUX_KMOD_SUFFIX) \
+	$(LINUX_DIR)/crypto/ocf/cryptosoft.$(LINUX_KMOD_SUFFIX) \
+	$(LINUX_DIR)/crypto/ocf/cryptodev.$(LINUX_KMOD_SUFFIX)
+  AUTOLOAD:=$(call AutoLoad,20,ocf cryptosoft cryptodev)
+endef
+
+$(eval $(call KernelPackage,linux-ocf))
+
+
 define KernelPackage/lp
   TITLE:=Parallel port and line printer support
   KCONFIG:=$(CONFIG_PARPORT)
@@ -297,6 +355,20 @@
 endef
 $(eval $(call KernelPackage,videodev))
 
+
+define KernelPackage/leds-alix
+  TITLE:=PCengines ALIX LED support
+  DESCRIPTION:=Kernel module for PCengines ALIX LEDs
+  DEPENDS:=@LINUX_2_6_X86_Alix
+  SUBMENU:=$(EMENU)
+  KCONFIG:=$(CONFIG_LEDS_ALIX)
+  FILES:=$(LINUX_DIR)/drivers/leds/leds-alix.$(LINUX_KMOD_SUFFIX)
+  AUTOLOAD:=$(call AutoLoad,50,leds-alix)
+endef
+$(eval $(call KernelPackage,leds-alix))
+
+
+
 define KernelPackage/leds-net48xx
   TITLE:=Soekris Net48xx LED support
   DESCRIPTION:=Kernel module for Soekris Net48xx LEDs
Binärdateien kamikaze_7.09.orig/package/madwifi/ath_hal-20080528.tgz and kamikaze_7.09/package/madwifi/ath_hal-20080528.tgz sind verschieden.
diff -Nur kamikaze_7.09.orig/package/madwifi/Config.in kamikaze_7.09/package/madwifi/Config.in
--- kamikaze_7.09.orig/package/madwifi/Config.in	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/Config.in	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,70 @@
+# MadWifi configuration
+
+config MADWIFI_DEBUG
+	bool "Enable compilation of debugging features"
+	depends on EXPERIMENTAL && PACKAGE_kmod-madwifi
+	default n
+
+choice
+	prompt "Rate control algorithm selection"
+	depends on PACKAGE_kmod-madwifi
+	default MADWIFI_RCA_MINSTREL
+	help
+	  This option controls how MadWifi chooses its bitrate.
+
+config MADWIFI_RCA_MINSTREL
+	bool "Use the Minstrel rate control algorithm"
+	help
+	  This code is takes a wandering minstrel approach. Wander around the
+	  different rates, singing wherever you can. And then, look at the
+	  performance, and make a choice. Note that the wandering minstrel will
+	  always wander in directions where he/she feels he/she will get paid
+	  the best for his/her work.
+
+config MADWIFI_RCA_ONOE
+	bool "Use the Onoe rate control algorithm"
+	help
+	  Onoe is a credit based RCA where the value of the credit is determined
+	  by the frequency of successful, erroneous and retransmissions
+	  accumulated during a fixed invocation period of 1000 ms. If less than
+	  10% of the packets need to be retransmitted at a particular rate, Onoe
+	  keeps increasing its credit point till the threshold value of 10 is
+	  reached. At this point, the current transmission rate is increased to
+	  the next available higher rate and the process repeated with credit
+	  score of zero. Similar logic holds for deducting the credit score and
+	  moving to a lower bit-rate for failed packet
+	  transmission/retransmission attempts. However, once a bit-rate has
+	  been marked as failure in the previous attempt, Onoe will not attempt
+	  to select that bit-rate until 10 seconds have elapsed since the last
+	  attempt. Due to the manner in which it operates, Onoe is conservative
+	  in rate selection and is less sensitive to individual packet failure.
+
+config MADWIFI_RCA_AMRR
+	bool "Use the AMRR rate control algorithm"
+	help
+	  AMRR uses Binary Exponential Backoff (BEB) technique to adapt the
+	  length (threshold) of the sampling period used to change the values of
+	  bit-rate and transmission count parameters. It uses probe packets and
+	  depending on their transmission status adaptively changes the threshold
+	  value. The adaptation mechanism ensures fewer failed
+	  transmission/retransmission and higher throughput by not switching to a
+	  higher rate as specified by the backoff mechanism. In addition to this,
+	  the AMRR employs heuristics to capture the short-term variations of the
+	  channel by judiciously setting the rate and transmission count
+	  parameters.
+
+config MADWIFI_RCA_SAMPLERATE
+	bool "Use the SampleRate rate control algorithm"
+	help
+	  SampleRate decides on the transmission bit-rate based on the past
+	  history of performance; it keeps a record of the number of successive
+	  failures, the number of successful transmits and the total transmission
+	  time along with the destination for that bit-rate. Stale samples are
+	  removed based on a EWMA windowing mechanism. If in the sampling
+	  process, no successful acknowledgment is received or the number of
+	  packets sent is multiple of 10 on a specific link, it transmits the
+	  packet with the highest rate which has not failed 4 successive times.
+	  Other than that it transmits packets at the rate which has the lowest
+	  average transmission time.
+
+endchoice
diff -Nur kamikaze_7.09.orig/package/madwifi/files/lib/wifi/madwifi.sh kamikaze_7.09/package/madwifi/files/lib/wifi/madwifi.sh
--- kamikaze_7.09.orig/package/madwifi/files/lib/wifi/madwifi.sh	2007-09-30 20:03:49.000000000 +0200
+++ kamikaze_7.09/package/madwifi/files/lib/wifi/madwifi.sh	2008-06-19 17:34:17.000000000 +0200
@@ -71,9 +71,12 @@
 )
 
 enable_atheros() {
+	local device="$1"
 	config_get channel "$device" channel
 	config_get vifs "$device" vifs
-	
+
+	[ auto = "$channel" ] && channel=0
+
 	local first=1
 	for vif in $vifs; do
 		nosbeacon=
@@ -113,8 +116,10 @@
 		config_get_bool hidden "$vif" hidden 0
 		iwpriv "$ifname" hide_ssid "$hidden"
 
-		config_get_bool ff "$vif" ff 0
-		iwpriv "$ifname" ff "$ff"
+		config_get ff "$vif" ff
+		if [ -n "$ff" ]; then
+			iwpriv "$ifname" ff "$ff"
+		fi
 
 		config_get wds "$vif" wds
 		case "$wds" in
@@ -156,43 +161,88 @@
 		esac
 		config_get ssid "$vif" ssid
 
-		[ "$mode" = "sta" ] && {
-			config_get_bool bgscan "$vif" bgscan 1
-			iwpriv "$ifname" bgscan "$bgscan"
-		}
+		config_get_bool bgscan "$vif" bgscan
+		[ -n "$bgscan" ] && iwpriv "$ifname" bgscan "$bgscan"
 
-		config_get_bool antdiv "$device" diversity 1
-		sysctl -w dev."$device".diversity="$antdiv" >&-
+		config_get_bool antdiv "$device" diversity
+		[ -n "$antdiv" ] && sysctl -w dev."$device".diversity="$antdiv" >&-
 
 		config_get antrx "$device" rxantenna
-		if [ -n "$antrx" ]; then
-			sysctl -w dev."$device".rxantenna="$antrx" >&-
-		fi
+		[ -n "$antrx" ] && sysctl -w dev."$device".rxantenna="$antrx" >&-
 
 		config_get anttx "$device" txantenna
-		if [ -n "$anttx" ]; then
-			sysctl -w dev."$device".txantenna="$anttx" >&-
-		fi
+		[ -n "$anttx" ] && sysctl -w dev."$device".txantenna="$anttx" >&-
 
 		config_get distance "$device" distance
-		if [ -n "$distance" ]; then
-			athctrl -i "$device" -d "$distance" >&-
-		fi
+		[ -n "$distance" ] && athctrl -i "$device" -d "$distance" >&-
 
 		config_get txpwr "$vif" txpower
-		if [ -n "$txpwr" ]; then
-			iwconfig "$ifname" txpower "${txpwr%%.*}"
-		fi
+		[ -n "$txpwr" ] && iwconfig "$ifname" txpower "${txpwr%%.*}"
+
+		config_get rate "$vif" rate
+		[ -n "$rate" ] && iwconfig "$ifname" rate "${rate%%.*}"
+
+		config_get mcast_rate "$vif" mcast_rate
+		[ -n "$mcast_rate" ] && iwpriv "$ifname" mcast_rate "${mcast_rate%%.*}"
 
 		config_get frag "$vif" frag
-		if [ -n "$frag" ]; then
-			iwconfig "$ifname" frag "${frag%%.*}"
-		fi
+		[ -n "$frag" ] && iwconfig "$ifname" frag "${frag%%.*}"
 
 		config_get rts "$vif" rts
-		if [ -n "$rts" ]; then
-			iwconfig "$ifname" rts "${rts%%.*}"
-		fi
+		[ -n "$rts" ] && iwconfig "$ifname" rts "${rts%%.*}"
+
+		config_get_bool doth "$vif" 80211h
+		[ -n "$doth" ] && iwpriv "$ifname" doth "$doth"
+
+		config_get_bool comp "$vif" compression
+		[ -n "$comp" ] && iwpriv "$ifname" compression "$comp"
+
+		config_get_bool minrate "$vif" minrate
+		[ -n "$minrate" ] && iwpriv "$ifname" minrate "$minrate"
+
+		config_get_bool maxrate "$vif" maxrate
+		[ -n "$maxrate" ] && iwpriv "$ifname" maxrate "$maxrate"
+
+		config_get_bool burst "$vif" bursting
+		[ -n "$burst" ] && iwpriv "$ifname" burst "$burst"
+
+		config_get_bool wmm "$vif" wmm
+		[ -n "$wmm" ] && iwpriv "$ifname" wmm "$wmm"
+
+		config_get_bool xr "$vif" xr
+		[ -n "$xr" ] && iwpriv "$ifname" xr "$xr"
+
+		config_get_bool ar "$vif" ar
+		[ -n "$ar" ] && iwpriv "$ifname" ar "$ar"
+
+		config_get_bool turbo "$vif" turbo
+		[ -n "$turbo" ] && iwpriv "$ifname" turbo "$turbo"
+
+		config_get_bool doth "$vif" doth 0
+		[ -n "$doth" ] && iwpriv "$ifname" doth "$doth"
+
+		config_get maclist "$vif" maclist
+		[ -n "$maclist" ] && {
+			# flush MAC list
+			iwpriv "$ifname" maccmd 3
+			for mac in $maclist; do
+				iwpriv "$ifname" addmac "$mac"
+			done
+		}
+
+		config_get macpolicy "$vif" macpolicy
+		case "$macpolicy" in
+			allow)
+				iwpriv "$ifname" maccmd 1
+			;;
+			deny)
+				iwpriv "$ifname" maccmd 2
+			;;
+			*)
+				# default deny policy if mac list exists
+				[ -n "$maclist" ] && iwpriv "$ifname" maccmd 2
+			;;
+		esac
 
 		ifconfig "$ifname" up
 		iwconfig "$ifname" channel "$channel" >/dev/null 2>/dev/null 
@@ -222,22 +272,34 @@
 				fi
 			;;
 			wds|sta)
-				case "$enc" in 
+				config_get_bool usepassphrase "$vif" passphrase 1
+				case "$enc" in
 					PSK|psk|PSK2|psk2)
 						case "$enc" in
 							PSK|psk)
-								proto='proto=WPA';;
+								proto='proto=WPA'
+								if [ "$usepassphrase" = "1" ]; then
+									passphrase="psk=\"${key}\""
+								else
+									passphrase="psk=${key}"
+								fi
+								;;
 							PSK2|psk2)
-								proto='proto=RSN';;
+								proto='proto=RSN'
+                                                                if [ "$usepassphrase" = "1" ]; then
+                                                                        passphrase="psk=\"${key}\""
+                                                                else
+                                                                        passphrase="psk=${key}"
+                                                                fi
+								;;
 						esac
 						cat > /var/run/wpa_supplicant-$ifname.conf <<EOF
-ctrl_interface=/var/run/wpa_supplicant
 network={
 	scan_ssid=1
 	ssid="$ssid"
 	key_mgmt=WPA-PSK
 	$proto
-	psk="$key"
+	$passphrase
 }
 EOF
 					;;
@@ -262,7 +324,7 @@
 		cat <<EOF
 config wifi-device  $dev
 	option type     atheros
-	option channel  5
+	option channel  auto
 
 	# REMOVE THIS LINE TO ENABLE WIFI:
 	option disabled 1
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/include/compat.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/include/compat.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/include/compat.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/include/compat.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: compat.h 3310 2008-01-30 20:23:49Z mentor $
+ */
+#ifndef _ATH_COMPAT_H_
+#define _ATH_COMPAT_H_
+
+/* Compatibility with older Linux kernels */
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/netdevice.h>
+#endif
+
+#if !defined(__KERNEL__) || !defined (__bitwise)
+#define __le16 u_int16_t
+#define __le32 u_int32_t
+#define __le64 u_int64_t
+#define __be16 u_int16_t
+#define __be32 u_int32_t
+#define __be64 u_int64_t
+#define __force
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({				\
+	    const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	    (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#ifndef list_for_each_entry_reverse
+#define list_for_each_entry_reverse(pos, head, member)			\
+	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
+	     prefetch(pos->member.prev), &pos->member != (head); 	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+#endif
+
+#ifndef NETDEV_TX_OK
+#define NETDEV_TX_OK    0
+#define NETDEV_TX_BUSY  1
+#endif
+
+/*
+ * BSD/Linux compatibility shims.  These are used mainly to
+ * minimize differences when importing necesary BSD code.
+ */
+#define	NBBY	8			/* number of bits/byte */
+
+/* roundup() appears in Linux 2.6.18 */
+#include <linux/kernel.h>
+#ifndef roundup
+#define	roundup(x, y)	((((x)+((y)-1))/(y))*(y))  /* to any y */
+#endif
+
+#define	howmany(x, y)	(((x)+((y)-1))/(y))
+
+/* Bit map related macros. */
+#define	setbit(a,i)	((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define	clrbit(a,i)	((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define	isset(a,i)	((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define	isclr(a,i)	(((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+
+#ifndef __packed
+#define	__packed	__attribute__((__packed__))
+#endif
+
+#define	__offsetof(t,m)	offsetof(t,m)
+
+#ifndef ALIGNED_POINTER
+/*
+ * ALIGNED_POINTER is a boolean macro that checks whether an address
+ * is valid to fetch data elements of type t from on this architecture.
+ * This does not reflect the optimal alignment, just the possibility
+ * (within reasonable limits). 
+ *
+ */
+#define ALIGNED_POINTER(p,t)	1
+#endif
+
+#ifdef __KERNEL__
+#define	KASSERT(exp, msg) do {			\
+	if (unlikely(!(exp))) {			\
+		printk msg;			\
+		BUG();				\
+	}					\
+} while (0)
+#endif /* __KERNEL__ */
+
+/*
+ * NetBSD/FreeBSD defines for file version.
+ */
+#define	__FBSDID(_s)
+#define	__KERNEL_RCSID(_n,_s)
+
+/*
+ * Fixes for Linux API changes
+ */
+#ifdef __KERNEL__
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
+#define ATH_REGISTER_SYSCTL_TABLE(t) register_sysctl_table(t, 1)
+#else
+#define ATH_REGISTER_SYSCTL_TABLE(t) register_sysctl_table(t)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
+#define __user
+#define __kernel
+#define __iomem
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+typedef int gfp_t;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_usec - rhs->tv_usec;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+#define skb_end_pointer(_skb) ((_skb)->end)
+#define skb_tail_pointer(_skb) ((_skb)->tail)
+#define skb_set_network_header(_skb, _offset) \
+	do { (_skb)->nh.raw = (_skb)->data + (_offset); } while(0)
+#define skb_reset_network_header(_skb) \
+	do { (_skb)->nh.raw = (_skb)->data; } while(0)
+#define skb_mac_header(_skb) ((_skb)->mac.raw)
+#define skb_reset_mac_header(_skb) \
+	do { (_skb)->mac.raw = (_skb)->data; } while(0)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#define CTL_AUTO -2
+#define DEV_ATH 9
+#else
+#define CTL_AUTO CTL_UNNUMBERED
+#define DEV_ATH CTL_UNNUMBERED
+#endif
+
+/* __skb_append got a third parameter in 2.6.14 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+#define __skb_queue_after(_list, _old, _new)	__skb_append(_old, _new)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+#define __skb_queue_after(_list, _old, _new)	__skb_append(_old, _new, _list)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _ATH_COMPAT_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/include/sys/queue.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/include/sys/queue.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/include/sys/queue.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/include/sys/queue.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: queue.h 2392 2007-05-29 21:55:25Z mtaylor $
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *				SLIST	LIST	STAILQ	TAILQ
+ * _HEAD			+	+	+	+
+ * _HEAD_INITIALIZER		+	+	+	+
+ * _ENTRY			+	+	+	+
+ * _INIT			+	+	+	+
+ * _EMPTY			+	+	+	+
+ * _FIRST			+	+	+	+
+ * _NEXT			+	+	+	+
+ * _PREV			-	-	-	+
+ * _LAST			-	-	+	+
+ * _FOREACH			+	+	+	+
+ * _FOREACH_SAFE		+	+	+	+
+ * _FOREACH_REVERSE		-	-	-	+
+ * _FOREACH_REVERSE_SAFE	-	-	-	+
+ * _INSERT_HEAD			+	+	+	+
+ * _INSERT_BEFORE		-	+	-	+
+ * _INSERT_AFTER		+	+	+	+
+ * _INSERT_TAIL			-	-	+	+
+ * _CONCAT			-	-	+	+
+ * _REMOVE_HEAD			+	-	+	-
+ * _REMOVE			+	+	+	+
+ *
+ */
+#define	QUEUE_MACRO_DEBUG 0
+#if QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+	char *lastfile;
+	int lastline;
+	char *prevfile;
+	int prevline;
+};
+
+#define	TRACEBUF	struct qm_trace trace;
+#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
+
+#define	QMD_TRACE_HEAD(head) do {					\
+	(head)->trace.prevline = (head)->trace.lastline;		\
+	(head)->trace.prevfile = (head)->trace.lastfile;		\
+	(head)->trace.lastline = __LINE__;				\
+	(head)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#define	QMD_TRACE_ELEM(elem) do {					\
+	(elem)->trace.prevline = (elem)->trace.lastline;		\
+	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
+	(elem)->trace.lastline = __LINE__;				\
+	(elem)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#else
+#define	QMD_TRACE_ELEM(elem)
+#define	QMD_TRACE_HEAD(head)
+#define	TRACEBUF
+#define	TRASHIT(x)
+#endif	/* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+
+#define	SLIST_FIRST(head)	((head)->slh_first)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != NULL;					\
+	    (varp) = &SLIST_NEXT((var), field))
+
+#define	SLIST_INIT(head) do {						\
+	SLIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
+	SLIST_NEXT((slistelm), field) = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
+	SLIST_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if (SLIST_FIRST((head)) == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = SLIST_FIRST((head));		\
+		while (SLIST_NEXT(curelm, field) != (elm))		\
+			curelm = SLIST_NEXT(curelm, field);		\
+		SLIST_NEXT(curelm, field) =				\
+		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
+	}								\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_CONCAT(head1, head2) do {				\
+	if (!STAILQ_EMPTY((head2))) {					\
+		*(head1)->stqh_last = (head2)->stqh_first;		\
+		(head1)->stqh_last = (head2)->stqh_last;		\
+		STAILQ_INIT((head2));					\
+	}								\
+} while (0)
+
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for ((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+
+#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = STAILQ_FIRST((head));				\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY((head)) ?						\
+		NULL :							\
+	        ((struct type *)					\
+		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		if ((STAILQ_NEXT(curelm, field) =			\
+		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+	}								\
+} while (0)
+
+
+#define	STAILQ_REMOVE_AFTER(head, elm, field) do {			\
+	if (STAILQ_NEXT(elm, field)) {		\
+		if ((STAILQ_NEXT(elm, field) =			\
+	 	    STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((elm), field); \
+	}								\
+} while (0)
+
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
+	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define	ATH_LIST_HEAD(name, type)					\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = LIST_FIRST((head));				\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	LIST_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
+} while (0)
+
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev = 		\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+	TRACEBUF							\
+}
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+	TRACEBUF							\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT((head2));					\
+		QMD_TRACE_HEAD(head);					\
+		QMD_TRACE_HEAD(head2);					\
+	}								\
+} while (0)
+
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
+	    (var) = (tvar))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    &TAILQ_NEXT((elm), field);				\
+	else {								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	TAILQ_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	TRASHIT((elm)->field.tqe_next);					\
+	TRASHIT((elm)->field.tqe_prev);					\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+
+#ifdef _KERNEL
+
+/*
+ * XXX insque() and remque() are an old way of handling certain queues.
+ * They bogusly assumes that all queue heads look alike.
+ */
+
+struct quehead {
+	struct quehead *qh_link;
+	struct quehead *qh_rlink;
+};
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+static __inline void
+insque(void *a, void *b)
+{
+	struct quehead *element = (struct quehead *)a,
+		 *head = (struct quehead *)b;
+
+	element->qh_link = head->qh_link;
+	element->qh_rlink = head;
+	head->qh_link = element;
+	element->qh_link->qh_rlink = element;
+}
+
+static __inline void
+remque(void *a)
+{
+	struct quehead *element = (struct quehead *)a;
+
+	element->qh_link->qh_rlink = element->qh_rlink;
+	element->qh_rlink->qh_link = element->qh_link;
+	element->qh_rlink = 0;
+}
+
+#else /* !(__GNUC__ || __INTEL_COMPILER) */
+
+void	insque(void *a, void *b);
+void	remque(void *a);
+
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_crypto.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_crypto.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_crypto.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_crypto.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_crypto.h 3068 2007-12-21 17:46:02Z mentor $
+ */
+#ifndef _NET80211_IEEE80211_CRYPTO_H_
+#define _NET80211_IEEE80211_CRYPTO_H_
+
+/*
+ * 802.11 protocol crypto-related definitions.
+ */
+#define	IEEE80211_KEYBUF_SIZE	16
+#define	IEEE80211_MICBUF_SIZE	(8 + 8)		/* space for both TX & RX keys */
+#define IEEE80211_TID_SIZE	17		/* total number of TIDs */
+
+/*
+ * Old WEP-style key.  Deprecated.
+ */
+struct ieee80211_wepkey {
+	u_int wk_len;				/* key length in bytes */
+	u_int8_t wk_key[IEEE80211_KEYBUF_SIZE];
+};
+
+struct ieee80211_cipher;
+
+/*
+ * Crypto key state.  There is sufficient room for all supported
+ * ciphers (see below).  The underlying ciphers are handled
+ * separately through loadable cipher modules that register with
+ * the generic crypto support.  A key has a reference to an instance
+ * of the cipher; any per-key state is hung off wk_private by the
+ * cipher when it is attached.  Ciphers are automatically called
+ * to detach and cleanup any such state when the key is deleted.
+ *
+ * The generic crypto support handles encap/decap of cipher-related
+ * frame contents for both hardware- and software-based implementations.
+ * A key requiring software crypto support is automatically flagged and
+ * the cipher is expected to honor this and do the necessary work.
+ * Ciphers such as TKIP may also support mixed hardware/software
+ * encrypt/decrypt and MIC processing.
+ */
+
+typedef u_int16_t ieee80211_keyix_t;
+
+/* XXX pack better? */
+/* XXX 48-bit rsc/tsc */
+struct ieee80211_key {
+	u_int8_t wk_keylen;		/* key length in bytes */
+	u_int8_t wk_flags;
+#define	IEEE80211_KEY_XMIT	0x01	/* key used for xmit */
+#define	IEEE80211_KEY_RECV	0x02	/* key used for recv */
+#define	IEEE80211_KEY_GROUP	0x04	/* key used for WPA group operation */
+#define	IEEE80211_KEY_SWCRYPT	0x10	/* host-based encrypt/decrypt */
+#define	IEEE80211_KEY_SWMIC	0x20	/* host-based enmic/demic */
+	ieee80211_keyix_t wk_keyix;	/* key index */
+	u_int8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
+#define	wk_txmic	wk_key+IEEE80211_KEYBUF_SIZE+0	/* XXX can't () right */
+#define	wk_rxmic	wk_key+IEEE80211_KEYBUF_SIZE+8	/* XXX can't () right */
+	u_int64_t wk_keyrsc[IEEE80211_TID_SIZE];	/* key receive sequence counter */
+	u_int64_t wk_keytsc;		/* key transmit sequence counter */
+	const struct ieee80211_cipher *wk_cipher;
+	void *wk_private;		/* private cipher state */
+};
+#define	IEEE80211_KEY_COMMON 		/* common flags passed in by apps */\
+	(IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP)
+
+/*
+ * NB: these values are ordered carefully; there are lots of
+ * of implications in any reordering.  In particular beware
+ * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
+ */
+#define	IEEE80211_CIPHER_WEP		0
+#define	IEEE80211_CIPHER_TKIP		1
+#define	IEEE80211_CIPHER_AES_OCB	2
+#define	IEEE80211_CIPHER_AES_CCM	3
+#define	IEEE80211_CIPHER_CKIP		5
+#define	IEEE80211_CIPHER_NONE		6	/* pseudo value */
+
+#define	IEEE80211_CIPHER_MAX		(IEEE80211_CIPHER_NONE + 1)
+
+#define	IEEE80211_KEYIX_NONE	((ieee80211_keyix_t)-1)
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+
+struct ieee80211com;
+struct ieee80211vap;
+struct ieee80211_node;
+struct sk_buff;
+
+void ieee80211_crypto_attach(struct ieee80211com *);
+void ieee80211_crypto_detach(struct ieee80211com *);
+void ieee80211_crypto_vattach(struct ieee80211vap *);
+void ieee80211_crypto_vdetach(struct ieee80211vap *);
+int ieee80211_crypto_newkey(struct ieee80211vap *, int, int,
+	struct ieee80211_key *);
+int ieee80211_crypto_delkey(struct ieee80211vap *, struct ieee80211_key *,
+	struct ieee80211_node *);
+int ieee80211_crypto_setkey(struct ieee80211vap *, struct ieee80211_key *,
+	const u_int8_t macaddr[IEEE80211_ADDR_LEN], struct ieee80211_node *);
+void ieee80211_crypto_delglobalkeys(struct ieee80211vap *);
+
+/*
+ * Template for a supported cipher.  Ciphers register with the
+ * crypto code and are typically loaded as separate modules
+ * (the null cipher is always present).
+ * XXX may need refcnts
+ */
+struct ieee80211_cipher {
+	const char *ic_name;		/* printable name */
+	u_int ic_cipher;		/* IEEE80211_CIPHER_* */
+	u_int ic_header;		/* size of privacy header (bytes) */
+	u_int ic_trailer;		/* size of privacy trailer (bytes) */
+	u_int ic_miclen;		/* size of mic trailer (bytes) */
+	void *(*ic_attach)(struct ieee80211vap *, struct ieee80211_key *);
+	void (*ic_detach)(struct ieee80211_key *);
+	int (*ic_setkey)(struct ieee80211_key *);
+	int (*ic_encap)(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+	int (*ic_decap)(struct ieee80211_key *, struct sk_buff *, int);
+	int (*ic_enmic)(struct ieee80211_key *, struct sk_buff *, int);
+	int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int, int);
+};
+extern const struct ieee80211_cipher ieee80211_cipher_none;
+
+void ieee80211_crypto_register(const struct ieee80211_cipher *);
+void ieee80211_crypto_unregister(const struct ieee80211_cipher *);
+int ieee80211_crypto_available(struct ieee80211vap*, u_int);
+
+struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
+	struct sk_buff *);
+struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
+	struct sk_buff *, int);
+
+/*
+ * Check and remove any MIC.
+ */
+static __inline int
+ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+	struct sk_buff *skb, int hdrlen, int force)
+{
+	const struct ieee80211_cipher *cip = k->wk_cipher;
+	return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen, force) : 1);
+}
+
+/*
+ * Add any MIC.
+ */
+static __inline int
+ieee80211_crypto_enmic(struct ieee80211vap *vap, struct ieee80211_key *k,
+	struct sk_buff *skb, int force)
+{
+	const struct ieee80211_cipher *cip = k->wk_cipher;
+	return (cip->ic_miclen > 0 ? cip->ic_enmic(k, skb, force) : 1);
+}
+
+/* 
+ * Reset key state to an unused state.  The crypto
+ * key allocation mechanism ensures other state (e.g.
+ * key data) is properly setup before a key is used.
+ */
+static __inline void
+ieee80211_crypto_resetkey(struct ieee80211vap *vap, struct ieee80211_key *k,
+	ieee80211_keyix_t ix)
+{
+	k->wk_cipher = &ieee80211_cipher_none;;
+	k->wk_private = k->wk_cipher->ic_attach(vap, k);
+	k->wk_keyix = ix;
+	k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
+}
+
+/*
+ * Crypto-related notification methods.
+ */
+void ieee80211_notify_replay_failure(struct ieee80211vap *,
+	const struct ieee80211_frame *, const struct ieee80211_key *,
+	u_int64_t rsc);
+void ieee80211_notify_michael_failure(struct ieee80211vap *,
+	const struct ieee80211_frame *, ieee80211_keyix_t keyix);
+#endif /* defined(__KERNEL__) || defined(_KERNEL) */
+#endif /* _NET80211_IEEE80211_CRYPTO_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_debug.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_debug.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_debug.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_debug.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_var.h 1969 2007-01-16 03:05:18Z scottr $
+ */
+#ifndef _NET80211_IEEE80211_DEBUG_H_
+#define _NET80211_IEEE80211_DEBUG_H_
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211.h>
+
+/* Set to true if ANY sc has skb debugging on */
+extern int ath_debug_global;
+enum {
+	GLOBAL_DEBUG_SKB_REF  = 0x00000040,	/* SKB reference counting */
+	GLOBAL_DEBUG_SKB      = 0x40000000,     /* SKB usage/leak debugging,
+	                                           must match ATH_DEBUG_SKB */
+};
+
+#define IEEE80211_MSG_NODE_REF  0x80000000      /* node ref counting */
+#define	IEEE80211_MSG_DEBUG	0x40000000	/* IFF_DEBUG equivalent */
+#define	IEEE80211_MSG_DUMPPKTS	0x20000000	/* IFF_LINK2 equivalent */
+#define	IEEE80211_MSG_CRYPTO	0x10000000	/* crypto work */
+#define	IEEE80211_MSG_INPUT	0x08000000	/* input handling */
+#define	IEEE80211_MSG_XRATE	0x04000000	/* rate set handling */
+#define	IEEE80211_MSG_ELEMID	0x02000000	/* element id parsing */
+#define	IEEE80211_MSG_NODE	0x01000000	/* node management */
+#define	IEEE80211_MSG_ASSOC	0x00800000	/* association handling */
+#define	IEEE80211_MSG_AUTH	0x00400000	/* authentication handling */
+#define	IEEE80211_MSG_SCAN	0x00200000	/* scanning */
+#define	IEEE80211_MSG_OUTPUT	0x00100000	/* output handling */
+#define	IEEE80211_MSG_STATE	0x00080000	/* state machine */
+#define	IEEE80211_MSG_POWER	0x00040000	/* power save handling */
+#define	IEEE80211_MSG_DOT1X	0x00020000	/* 802.1x authenticator */
+#define	IEEE80211_MSG_DOT1XSM	0x00010000	/* 802.1x state machine */
+#define	IEEE80211_MSG_RADIUS	0x00008000	/* 802.1x radius client */
+#define	IEEE80211_MSG_RADDUMP	0x00004000	/* dump 802.1x radius packets */
+#define	IEEE80211_MSG_RADKEYS	0x00002000	/* dump 802.1x keys */
+#define	IEEE80211_MSG_WPA	0x00001000	/* WPA/RSN protocol */
+#define	IEEE80211_MSG_ACL	0x00000800	/* ACL handling */
+#define	IEEE80211_MSG_WME	0x00000400	/* WME protocol */
+#define	IEEE80211_MSG_SUPG	0x00000200	/* SUPERG */
+#define	IEEE80211_MSG_DOTH	0x00000100	/* 11.h */
+#define	IEEE80211_MSG_INACT	0x00000080	/* inactivity handling */
+#define	IEEE80211_MSG_ROAM	0x00000040	/* sta-mode roaming */
+
+#define	IEEE80211_MSG_ANY	0xffffffff	/* anything */
+
+#define IEEE80211_MSG_IC	(IEEE80211_MSG_NODE_REF) /* shared for all VAP */
+
+#ifdef IEEE80211_DEBUG
+#define ieee80211_msg_is_reported(_vap, m) \
+	(!!(((_vap)->iv_debug | (_vap)->iv_ic->ic_debug) & (m)))
+#define	IEEE80211_DPRINTF(_vap, _m, _fmt, ...) do {			\
+	if (ieee80211_msg_is_reported(_vap, _m))					\
+		ieee80211_note(_vap, _fmt, __VA_ARGS__);		\
+} while (0)
+#define	IEEE80211_NOTE(_vap, _m, _ni, _fmt, ...) do {			\
+	if (ieee80211_msg_is_reported(_vap, _m))					\
+		ieee80211_note_mac(_vap, (_ni)->ni_macaddr, _fmt, __VA_ARGS__);\
+} while (0)
+#define	IEEE80211_NOTE_MAC(_vap, _m, _mac, _fmt, ...) do {		\
+	if (ieee80211_msg_is_reported(_vap, _m))					\
+		ieee80211_note_mac(_vap, _mac, _fmt, __VA_ARGS__);	\
+} while (0)
+#define	IEEE80211_NOTE_FRAME(_vap, _m, _wh, _fmt, ...) do {		\
+	if (ieee80211_msg_is_reported(_vap, _m))					\
+		ieee80211_note_frame(_vap, _wh, _fmt, __VA_ARGS__);	\
+} while (0)
+struct ieee80211vap;
+struct ieee80211_frame;
+void ieee80211_note(struct ieee80211vap *, const char *, ...);
+void ieee80211_note_mac(struct ieee80211vap *,
+	const u_int8_t mac[IEEE80211_ADDR_LEN], const char *, ...);
+void ieee80211_note_frame(struct ieee80211vap *,
+	const struct ieee80211_frame *, const char *, ...);
+#define	ieee80211_msg_debug(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_DEBUG)
+#define	ieee80211_msg_dumppkts(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_DUMPPKTS)
+#define	ieee80211_msg_input(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_INPUT)
+#define	ieee80211_msg_radius(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_RADIUS)
+#define	ieee80211_msg_dumpradius(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_RADDUMP)
+#define	ieee80211_msg_dumpradkeys(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_RADKEYS)
+#define	ieee80211_msg_scan(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_SCAN)
+#define	ieee80211_msg_assoc(_vap) \
+	ieee80211_msg_is_reported(_vap, IEEE80211_MSG_ASSOC)
+#else /* IEEE80211_DEBUG */
+#define	ieee80211_msg_is_reported(_vap, _m)	(0)
+#define	IEEE80211_DPRINTF(_vap, _m, _fmt, ...)
+#define	IEEE80211_NOTE(_vap, _m, _wh, _fmt, ...)
+#define	IEEE80211_NOTE_FRAME(_vap, _m, _wh, _fmt, ...)
+#define	IEEE80211_NOTE_MAC(_vap, _m, _mac, _fmt, ...)
+#endif /* IEEE80211_DEBUG */
+
+#endif /* _NET80211_IEEE80211_DEBUG_H_ */
+
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/_ieee80211.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/_ieee80211.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/_ieee80211.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/_ieee80211.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,324 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: _ieee80211.h 3207 2008-01-18 21:25:05Z mtaylor $
+ */
+#ifndef _NET80211__IEEE80211_H_
+#define _NET80211__IEEE80211_H_
+
+enum ieee80211_phytype {
+	IEEE80211_T_DS,			/* direct sequence spread spectrum */
+	IEEE80211_T_FH,			/* frequency hopping */
+	IEEE80211_T_OFDM,		/* frequency division multiplexing */
+	IEEE80211_T_TURBO,		/* high rate OFDM, aka turbo mode */
+};
+#define	IEEE80211_T_CCK	IEEE80211_T_DS	/* more common nomenclature */
+
+/* XXX: not really a mode; there are really multiple PHYs */
+enum ieee80211_phymode {
+	IEEE80211_MODE_AUTO	= 0,	/* autoselect */
+	IEEE80211_MODE_11A	= 1,	/* 5GHz, OFDM */
+	IEEE80211_MODE_11B	= 2,	/* 2GHz, CCK */
+	IEEE80211_MODE_11G	= 3,	/* 2GHz, OFDM */
+	IEEE80211_MODE_FH	= 4,	/* 2GHz, GFSK */
+	IEEE80211_MODE_TURBO_A	= 5,	/* 5GHz, OFDM, 2x clock dynamic turbo */
+	IEEE80211_MODE_TURBO_G	= 6,	/* 2GHz, OFDM, 2x clock  dynamic turbo*/
+};
+#define	IEEE80211_MODE_MAX	(IEEE80211_MODE_TURBO_G+1)
+
+enum ieee80211_opmode {
+	IEEE80211_M_STA		= 1,	/* infrastructure station */
+	IEEE80211_M_IBSS 	= 0,	/* IBSS (adhoc) station */
+	IEEE80211_M_AHDEMO	= 3,	/* Old lucent compatible adhoc demo */
+	IEEE80211_M_HOSTAP	= 6,	/* Software Access Point */
+	IEEE80211_M_MONITOR	= 8,	/* Monitor mode */
+	IEEE80211_M_WDS		= 2	/* WDS link */
+};
+
+/*
+ * True if this mode will send beacon on a regular interval, like AP
+ * or IBSS
+ */
+#define IEEE80211_IS_MODE_BEACON(_opmode) \
+	((_opmode == IEEE80211_M_IBSS) || \
+	 (_opmode == IEEE80211_M_HOSTAP))
+
+/*
+ * True if this mode must behave like a DFS master, ie do Channel
+ * Check Availability and In Service Monitoring. We need to make sure
+ * that all modes cannot send data without being authorized. Such
+ * enforcement is not done in monitor mode however.
+ */
+
+#define IEEE80211_IS_MODE_DFS_MASTER(_opmode) \
+	((_opmode == IEEE80211_M_IBSS) || \
+	 (_opmode == IEEE80211_M_AHDEMO) || \
+	 (_opmode == IEEE80211_M_HOSTAP) || \
+	 (_opmode == IEEE80211_M_WDS))
+
+/*
+ * 802.11g protection mode.
+ */
+enum ieee80211_protmode {
+	IEEE80211_PROT_NONE	= 0,	/* no protection */
+	IEEE80211_PROT_CTSONLY	= 1,	/* CTS to self */
+	IEEE80211_PROT_RTSCTS	= 2,	/* RTS-CTS */
+};
+
+/*
+ * Authentication mode.
+ */
+enum ieee80211_authmode {
+	IEEE80211_AUTH_NONE	= 0,
+	IEEE80211_AUTH_OPEN	= 1,	/* open */
+	IEEE80211_AUTH_SHARED	= 2,	/* shared-key */
+	IEEE80211_AUTH_8021X	= 3,	/* 802.1x */
+	IEEE80211_AUTH_AUTO	= 4,	/* auto-select/accept */
+	/* NB: these are used only for ioctls */
+	IEEE80211_AUTH_WPA	= 5,	/* WPA/RSN w/ 802.1x/PSK */
+};
+
+/*
+ * Roaming mode is effectively who controls the operation
+ * of the 802.11 state machine when operating as a station.
+ * State transitions are controlled either by the driver
+ * (typically when management frames are processed by the
+ * hardware/firmware), the host (auto/normal operation of
+ * the 802.11 layer), or explicitly through ioctl requests
+ * when applications like wpa_supplicant want control.
+ */
+enum ieee80211_roamingmode {
+	IEEE80211_ROAMING_DEVICE= 0,	/* driver/hardware control */
+	IEEE80211_ROAMING_AUTO	= 1,	/* 802.11 layer control */
+	IEEE80211_ROAMING_MANUAL= 2,	/* application control */
+};
+
+/*
+ * Scanning mode controls station scanning work; this is
+ * used only when roaming mode permits the host to select
+ * the bss to join/channel to use.
+ */
+enum ieee80211_scanmode {
+	IEEE80211_SCAN_DEVICE	= 0,	/* driver/hardware control */
+	IEEE80211_SCAN_BEST	= 1,	/* 802.11 layer selects best */
+	IEEE80211_SCAN_FIRST	= 2,	/* take first suitable candidate */
+};
+
+enum ieee80211_scanflags {
+	IEEE80211_NOSCAN_DEFAULT = (1 << 0),
+	IEEE80211_NOSCAN_SET     = (1 << 1),
+};
+
+/*
+ * Channels are specified by frequency and attributes.
+ */
+struct ieee80211_channel {
+	u_int16_t ic_freq;	/* setting in MHz */
+	u_int16_t ic_flags;	/* see below */
+	u_int8_t ic_ieee;	/* IEEE channel number */
+	int8_t ic_maxregpower;	/* maximum regulatory tx power in dBm */
+	int8_t ic_maxpower;	/* maximum tx power in dBm */
+	int8_t ic_minpower;	/* minimum tx power in dBm */
+	u_int8_t ic_scanflags;
+};
+
+#define	IEEE80211_CHAN_MAX	255
+#define	IEEE80211_CHAN_BYTES	32	/* howmany(IEEE80211_CHAN_MAX, NBBY) */
+#define	IEEE80211_CHAN_ANY	0xffff	/* token for ``any channel'' */
+#define	IEEE80211_CHAN_ANYC 	((struct ieee80211_channel *) IEEE80211_CHAN_ANY)
+
+#define	IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT	0
+#define IEEE80211_DEFAULT_CHANCHANGE_TBTT_COUNT	3
+
+#define	IEEE80211_RADAR_TEST_MUTE_CHAN	36	/* Move to channel 36 for mute test */
+
+/* bits 0-3 are for private use by drivers */
+/* channel attributes */
+#define	IEEE80211_CHAN_TURBO	0x0010	/* Turbo channel */
+#define	IEEE80211_CHAN_CCK	0x0020	/* CCK channel */
+#define	IEEE80211_CHAN_OFDM	0x0040	/* OFDM channel */
+#define	IEEE80211_CHAN_2GHZ	0x0080	/* 2 GHz spectrum channel. */
+#define	IEEE80211_CHAN_5GHZ	0x0100	/* 5 GHz spectrum channel */
+#define	IEEE80211_CHAN_PASSIVE	0x0200	/* Only passive scan allowed */
+#define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
+#define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
+#define IEEE80211_CHAN_RADAR	0x1000	/* Radar found on channel */
+#define	IEEE80211_CHAN_STURBO	0x2000	/* 11a static turbo channel only */
+#define	IEEE80211_CHAN_HALF	0x4000	/* Half rate channel */
+#define	IEEE80211_CHAN_QUARTER	0x8000	/* Quarter rate channel */
+
+/*
+ * Useful combinations of channel characteristics.
+ */
+#define	IEEE80211_CHAN_FHSS \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
+#define	IEEE80211_CHAN_A \
+	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
+#define	IEEE80211_CHAN_B \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
+#define	IEEE80211_CHAN_PUREG \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
+#define	IEEE80211_CHAN_G \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
+#define IEEE80211_CHAN_108A \
+	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
+#define	IEEE80211_CHAN_108G \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
+#define	IEEE80211_CHAN_ST \
+	(IEEE80211_CHAN_108A | IEEE80211_CHAN_STURBO)
+
+#define	IEEE80211_CHAN_ALL \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_GFSK | \
+	 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN)
+#define	IEEE80211_CHAN_ALLTURBO \
+	(IEEE80211_CHAN_ALL | IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)
+
+#define	IEEE80211_IS_CHAN_FHSS(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
+#define	IEEE80211_IS_CHAN_A(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
+#define	IEEE80211_IS_CHAN_B(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
+#define	IEEE80211_IS_CHAN_PUREG(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
+#define	IEEE80211_IS_CHAN_G(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
+#define	IEEE80211_IS_CHAN_ANYG(_c) \
+	(IEEE80211_IS_CHAN_PUREG(_c) || IEEE80211_IS_CHAN_G(_c))
+#define	IEEE80211_IS_CHAN_ST(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_ST) == IEEE80211_CHAN_ST)
+#define	IEEE80211_IS_CHAN_108A(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_108A) == IEEE80211_CHAN_108A)
+#define	IEEE80211_IS_CHAN_108G(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G)
+
+#define	IEEE80211_IS_CHAN_2GHZ(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_2GHZ) != 0)
+#define	IEEE80211_IS_CHAN_5GHZ(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_5GHZ) != 0)
+#define	IEEE80211_IS_CHAN_OFDM(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_OFDM) != 0)
+#define	IEEE80211_IS_CHAN_CCK(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_CCK) != 0)
+#define	IEEE80211_IS_CHAN_GFSK(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_GFSK) != 0)
+#define	IEEE80211_IS_CHAN_TURBO(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_TURBO) != 0)
+#define	IEEE80211_IS_CHAN_STURBO(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_STURBO) != 0)
+#define	IEEE80211_IS_CHAN_DTURBO(_c) \
+	(((_c)->ic_flags & \
+	(IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)) == IEEE80211_CHAN_TURBO)
+#define	IEEE80211_IS_CHAN_HALF(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_HALF) != 0)
+#define	IEEE80211_IS_CHAN_QUARTER(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_QUARTER) != 0)
+
+#define	IEEE80211_IS_CHAN_RADAR(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_RADAR) != 0)
+#define	IEEE80211_IS_CHAN_PASSIVE(_c) \
+	(((_c)->ic_flags & IEEE80211_CHAN_PASSIVE) != 0)
+#define	IEEE80211_ARE_CHANS_SAME_MODE(_a, _b) \
+	(((_a)->ic_flags & IEEE80211_CHAN_ALLTURBO) == ((_b)->ic_flags & IEEE80211_CHAN_ALLTURBO))
+
+/* ni_chan encoding for FH phy */
+#define	IEEE80211_FH_CHANMOD		80
+#define	IEEE80211_FH_CHAN(set,pat)	(((set) - 1) * IEEE80211_FH_CHANMOD + (pat))
+#define	IEEE80211_FH_CHANSET(chan)	((chan) / IEEE80211_FH_CHANMOD + 1)
+#define	IEEE80211_FH_CHANPAT(chan)	((chan) % IEEE80211_FH_CHANMOD)
+
+/*
+ * Spectrum Management (IEEE 802.11h-2003)
+ */
+
+/* algorithm for (re)association based on supported channels
+ * (the one mentioned in 11.6.1 as out of scope of .11h) */
+enum ieee80211_sc_algorithm {
+	IEEE80211_SC_NONE,
+	/*
+	 * Do not disallow anyone from associating. When needed, channel will
+	 * be switched to the most suitable channel, no matter client stations
+	 * support it or not.
+	 */
+
+	IEEE80211_SC_LOOSE,
+	/*
+	 * Do not disallow anyone from associating. When needed, channel will
+	 * be switched to a suitable channel, which will be chosen taking
+	 * ni->ni_suppchans and ic->ic_sc_sldg under consideration.
+	 */
+
+	IEEE80211_SC_TIGHT,
+	/*
+	 * Allow to associate if there are at least ic->ic_mincom channels
+	 * common to the associating station and all of the already associated
+	 * stations. If the number of new common channels is less than
+	 * required, consider disassociating some other STAs. Such a
+	 * disassociation will be performed if (and only if) the association we
+	 * are currently considering would be then possible and the count of
+	 * the resultant set of common channels (ic_chan_nodes[i] ==
+	 * ic_cn_total) would increase by some amount. Whether the number of
+	 * the new channels that could be gained is enough to sacrifice a
+	 * number of STAs is determined by the ic->ic_slcg parameter.
+	 */
+
+	IEEE80211_SC_STRICT
+	/*
+	 * Basically the same behavior as IEEE80211_SC_TIGHT, except that if a
+	 * station does not specify Supported Channels, then it is denied to
+	 * associate.
+	 */
+};
+
+/*
+ * 802.11 rate set.
+ */
+#define	IEEE80211_RATE_SIZE	8		/* 802.11 standard */
+#define	IEEE80211_RATE_MAXSIZE	15		/* max rates we'll handle */
+#define	IEEE80211_SANITISE_RATESIZE(_rsz) \
+	((_rsz > IEEE80211_RATE_MAXSIZE) ? IEEE80211_RATE_MAXSIZE : _rsz)
+
+struct ieee80211_rateset {
+	u_int8_t rs_nrates;
+	u_int8_t rs_rates[IEEE80211_RATE_MAXSIZE];
+};
+
+struct ieee80211_roam {
+	int8_t rssi11a;		/* rssi thresh for 11a bss */
+	int8_t rssi11b;		/* for 11g sta in 11b bss */
+	int8_t rssi11bOnly;	/* for 11b sta */
+	u_int8_t pad1;
+	u_int8_t rate11a;	/* rate thresh for 11a bss */
+	u_int8_t rate11b;	/* for 11g sta in 11b bss */
+	u_int8_t rate11bOnly;	/* for 11b sta */
+	u_int8_t pad2;
+};
+#endif /* _NET80211__IEEE80211_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,999 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211.h 3268 2008-01-26 20:48:11Z mtaylor $
+ */
+#ifndef _NET80211_IEEE80211_H_
+#define _NET80211_IEEE80211_H_
+
+/*
+ * 802.11 protocol definitions.
+ */
+
+#define	IEEE80211_ADDR_LEN		6		/* size of 802.11 address */
+/* is 802.11 address multicast/broadcast? */
+#define	IEEE80211_IS_MULTICAST(_a)	(*(_a) & 0x01)
+
+/* IEEE 802.11 PLCP header */
+struct ieee80211_plcp_hdr {
+	u_int16_t i_sfd;
+	u_int8_t i_signal;
+	u_int8_t i_service;
+	u_int16_t i_length;
+	u_int16_t i_crc;
+} __packed;
+
+#define IEEE80211_PLCP_SFD      0xF3A0
+#define IEEE80211_PLCP_SERVICE  0x00
+
+/*
+ * generic definitions for IEEE 802.11 frames
+ */
+struct ieee80211_frame {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+	u_int8_t i_seq[2];
+	/* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
+	/* see below */
+} __packed;
+
+struct ieee80211_qosframe {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+	u_int8_t i_seq[2];
+	u_int8_t i_qos[2];
+	/* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
+	/* see below */
+} __packed;
+
+struct ieee80211_qoscntl {
+	u_int8_t i_qos[2];
+};
+
+struct ieee80211_frame_addr4 {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+	u_int8_t i_seq[2];
+	u_int8_t i_addr4[IEEE80211_ADDR_LEN];
+} __packed;
+
+
+struct ieee80211_qosframe_addr4 {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+	u_int8_t i_seq[2];
+	u_int8_t i_addr4[IEEE80211_ADDR_LEN];
+	u_int8_t i_qos[2];
+} __packed;
+
+struct ieee80211_ctlframe_addr2 {
+	u_int8_t i_fc[2];
+	__le16 i_aidordur; /* AID or duration */
+	u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+} __packed;
+
+#define	IEEE80211_FC0_VERSION_MASK		0x03
+#define	IEEE80211_FC0_VERSION_SHIFT		0
+#define	IEEE80211_FC0_VERSION_0			0x00
+#define	IEEE80211_FC0_TYPE_MASK			0x0c
+#define	IEEE80211_FC0_TYPE_SHIFT		2
+#define	IEEE80211_FC0_TYPE_MGT			0x00
+#define	IEEE80211_FC0_TYPE_CTL			0x04
+#define	IEEE80211_FC0_TYPE_DATA			0x08
+
+#define	IEEE80211_FC0_SUBTYPE_MASK		0xf0
+#define	IEEE80211_FC0_SUBTYPE_SHIFT		4
+/* for TYPE_MGT */
+#define	IEEE80211_FC0_SUBTYPE_ASSOC_REQ		0x00
+#define	IEEE80211_FC0_SUBTYPE_ASSOC_RESP	0x10
+#define	IEEE80211_FC0_SUBTYPE_REASSOC_REQ	0x20
+#define	IEEE80211_FC0_SUBTYPE_REASSOC_RESP	0x30
+#define	IEEE80211_FC0_SUBTYPE_PROBE_REQ		0x40
+#define	IEEE80211_FC0_SUBTYPE_PROBE_RESP	0x50
+#define	IEEE80211_FC0_SUBTYPE_BEACON		0x80
+#define	IEEE80211_FC0_SUBTYPE_ATIM		0x90
+#define	IEEE80211_FC0_SUBTYPE_DISASSOC		0xa0
+#define	IEEE80211_FC0_SUBTYPE_AUTH		0xb0
+#define	IEEE80211_FC0_SUBTYPE_DEAUTH		0xc0
+#define IEEE80211_FC0_SUBTYPE_ACTION		0xd0
+/* for TYPE_CTL */
+#define	IEEE80211_FC0_SUBTYPE_PS_POLL		0xa0
+#define	IEEE80211_FC0_SUBTYPE_RTS		0xb0
+#define	IEEE80211_FC0_SUBTYPE_CTS		0xc0
+#define	IEEE80211_FC0_SUBTYPE_ACK		0xd0
+#define	IEEE80211_FC0_SUBTYPE_CF_END		0xe0
+#define	IEEE80211_FC0_SUBTYPE_CF_END_ACK	0xf0
+/* for TYPE_DATA (bit combination) */
+#define	IEEE80211_FC0_SUBTYPE_DATA		0x00
+#define	IEEE80211_FC0_SUBTYPE_CF_ACK		0x10
+#define	IEEE80211_FC0_SUBTYPE_CF_POLL		0x20
+#define	IEEE80211_FC0_SUBTYPE_CF_ACPL		0x30
+#define	IEEE80211_FC0_SUBTYPE_NODATA		0x40
+#define	IEEE80211_FC0_SUBTYPE_CFACK		0x50
+#define	IEEE80211_FC0_SUBTYPE_CFPOLL		0x60
+#define	IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK	0x70
+#define	IEEE80211_FC0_SUBTYPE_QOS		0x80
+#define	IEEE80211_FC0_SUBTYPE_QOS_NULL		0xc0
+
+#define	IEEE80211_FC1_DIR_MASK			0x03
+#define	IEEE80211_FC1_DIR_NODS			0x00	/* STA->STA */
+#define	IEEE80211_FC1_DIR_TODS			0x01	/* STA->AP  */
+#define	IEEE80211_FC1_DIR_FROMDS		0x02	/* AP ->STA */
+#define	IEEE80211_FC1_DIR_DSTODS		0x03	/* AP ->AP  */
+
+#define	IEEE80211_FC1_MORE_FRAG			0x04
+#define	IEEE80211_FC1_RETRY			0x08
+#define	IEEE80211_FC1_PWR_MGT			0x10
+#define	IEEE80211_FC1_MORE_DATA			0x20
+#define	IEEE80211_FC1_PROT			0x40
+#define	IEEE80211_FC1_ORDER			0x80
+
+#define	IEEE80211_SEQ_FRAG_MASK			0x000f
+#define	IEEE80211_SEQ_FRAG_SHIFT		0
+#define	IEEE80211_SEQ_SEQ_MASK			0xfff0
+#define	IEEE80211_SEQ_SEQ_SHIFT			4
+
+#define	IEEE80211_SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
+
+#define	IEEE80211_NWID_LEN			32
+
+#define	IEEE80211_QOS_TXOP			0x00ff
+/* bit 8 is reserved */
+#define	IEEE80211_QOS_ACKPOLICY			0x60
+#define	IEEE80211_QOS_ACKPOLICY_S		5
+#define	IEEE80211_QOS_EOSP			0x10
+#define	IEEE80211_QOS_EOSP_S			4
+#define	IEEE80211_QOS_TID			0x0f
+
+#define IEEE80211_FRM_HAS_BODY(_wh)			\
+	(((_wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=	\
+			IEEE80211_FC0_TYPE_CTL)
+
+/*
+ * Country/Region Codes from MS WINNLS.H
+ * Numbering from ISO 3166
+ * XXX belongs elsewhere
+ */
+enum CountryCode {
+	CTRY_ALBANIA              = 8,       /* Albania */
+	CTRY_ALGERIA              = 12,      /* Algeria */
+	CTRY_ARGENTINA            = 32,      /* Argentina */
+	CTRY_ARMENIA              = 51,      /* Armenia */
+	CTRY_AUSTRALIA            = 36,      /* Australia */
+	CTRY_AUSTRIA              = 40,      /* Austria */
+	CTRY_AZERBAIJAN           = 31,      /* Azerbaijan */
+	CTRY_BAHRAIN              = 48,      /* Bahrain */
+	CTRY_BELARUS              = 112,     /* Belarus */
+	CTRY_BELGIUM              = 56,      /* Belgium */
+	CTRY_BELIZE               = 84,      /* Belize */
+	CTRY_BOLIVIA              = 68,      /* Bolivia */
+	CTRY_BRAZIL               = 76,      /* Brazil */
+	CTRY_BRUNEI_DARUSSALAM    = 96,      /* Brunei Darussalam */
+	CTRY_BULGARIA             = 100,     /* Bulgaria */
+	CTRY_CANADA               = 124,     /* Canada */
+	CTRY_CHILE                = 152,     /* Chile */
+	CTRY_CHINA                = 156,     /* People's Republic of China */
+	CTRY_COLOMBIA             = 170,     /* Colombia */
+	CTRY_COSTA_RICA           = 188,     /* Costa Rica */
+	CTRY_CROATIA              = 191,     /* Croatia */
+	CTRY_CYPRUS               = 196,
+	CTRY_CZECH                = 203,     /* Czech Republic */
+	CTRY_DENMARK              = 208,     /* Denmark */
+	CTRY_DOMINICAN_REPUBLIC   = 214,     /* Dominican Republic */
+	CTRY_ECUADOR              = 218,     /* Ecuador */
+	CTRY_EGYPT                = 818,     /* Egypt */
+	CTRY_EL_SALVADOR          = 222,     /* El Salvador */
+	CTRY_ESTONIA              = 233,     /* Estonia */
+	CTRY_FAEROE_ISLANDS       = 234,     /* Faeroe Islands */
+	CTRY_FINLAND              = 246,     /* Finland */
+	CTRY_FRANCE               = 250,     /* France */
+	CTRY_FRANCE2              = 255,     /* France2 */
+	CTRY_GEORGIA              = 268,     /* Georgia */
+	CTRY_GERMANY              = 276,     /* Germany */
+	CTRY_GREECE               = 300,     /* Greece */
+	CTRY_GUATEMALA            = 320,     /* Guatemala */
+	CTRY_HONDURAS             = 340,     /* Honduras */
+	CTRY_HONG_KONG            = 344,     /* Hong Kong S.A.R., P.R.C. */
+	CTRY_HUNGARY              = 348,     /* Hungary */
+	CTRY_ICELAND              = 352,     /* Iceland */
+	CTRY_INDIA                = 356,     /* India */
+	CTRY_INDONESIA            = 360,     /* Indonesia */
+	CTRY_IRAN                 = 364,     /* Iran */
+	CTRY_IRAQ                 = 368,     /* Iraq */
+	CTRY_IRELAND              = 372,     /* Ireland */
+	CTRY_ISRAEL               = 376,     /* Israel */
+	CTRY_ITALY                = 380,     /* Italy */
+	CTRY_JAMAICA              = 388,     /* Jamaica */
+	CTRY_JAPAN                = 392,     /* Japan */
+	CTRY_JAPAN1               = 393,     /* Japan (JP1) */
+	CTRY_JAPAN2               = 394,     /* Japan (JP0) */
+	CTRY_JAPAN3               = 395,     /* Japan (JP1-1) */
+	CTRY_JAPAN4               = 396,     /* Japan (JE1) */
+	CTRY_JAPAN5               = 397,     /* Japan (JE2) */
+	CTRY_JAPAN6               = 399,	 /* Japan (JP6) */
+	CTRY_JAPAN7               = 900,	 /* Japan */
+	CTRY_JAPAN8               = 901,	 /* Japan */
+	CTRY_JAPAN9               = 902,	 /* Japan */
+	CTRY_JAPAN10	      = 903,	 /* Japan */
+	CTRY_JAPAN11	      = 904,	 /* Japan */
+	CTRY_JAPAN12	      = 905,	 /* Japan */
+	CTRY_JAPAN13	      = 906,	 /* Japan */
+	CTRY_JAPAN14	      = 907,	 /* Japan */
+	CTRY_JAPAN15	      = 908,	 /* Japan */
+	CTRY_JAPAN16	      = 909,	 /* Japan */
+	CTRY_JAPAN17	      = 910,	 /* Japan */
+	CTRY_JAPAN18	      = 911,	 /* Japan */
+	CTRY_JAPAN19	      = 912,	 /* Japan */
+	CTRY_JAPAN20	      = 913,	 /* Japan */
+	CTRY_JAPAN21	      = 914,	 /* Japan */
+	CTRY_JAPAN22	      = 915,	 /* Japan */
+	CTRY_JAPAN23	      = 916,	 /* Japan */
+	CTRY_JAPAN24	      = 917,	 /* Japan */
+	CTRY_JAPAN25	      = 918,	 /* Japan */
+	CTRY_JAPAN26	      = 919,	 /* Japan */
+	CTRY_JAPAN27	      = 920,	 /* Japan */
+	CTRY_JAPAN28	      = 921,	 /* Japan */
+	CTRY_JAPAN29	      = 922,	 /* Japan */
+	CTRY_JAPAN30	      = 923,	 /* Japan */
+	CTRY_JAPAN31	      = 924,	 /* Japan */
+	CTRY_JAPAN32	      = 925,	 /* Japan */
+	CTRY_JAPAN33	      = 926,	 /* Japan */
+	CTRY_JAPAN34	      = 927,	 /* Japan */
+	CTRY_JAPAN35	      = 928,	 /* Japan */
+	CTRY_JAPAN36	      = 929,	 /* Japan */
+	CTRY_JAPAN37	      = 930,	 /* Japan */
+	CTRY_JAPAN38	      = 931,	 /* Japan */
+	CTRY_JAPAN39	      = 932,	 /* Japan */
+	CTRY_JAPAN40	      = 933,	 /* Japan */
+	CTRY_JAPAN41	      = 934,	 /* Japan */
+	CTRY_JAPAN42	      = 935,	 /* Japan */
+	CTRY_JAPAN43	      = 936,	 /* Japan */
+	CTRY_JAPAN44	      = 937,	 /* Japan */
+	CTRY_JAPAN45	      = 938,	 /* Japan */
+	CTRY_JAPAN46	      = 939,	 /* Japan */
+	CTRY_JAPAN47	      = 940,	 /* Japan */
+	CTRY_JAPAN48	      = 941,	 /* Japan */
+	CTRY_JORDAN               = 400,     /* Jordan */
+	CTRY_KAZAKHSTAN           = 398,     /* Kazakhstan */
+	CTRY_KENYA                = 404,     /* Kenya */
+	CTRY_KOREA_NORTH          = 408,     /* North Korea */
+	CTRY_KOREA_ROC            = 410,     /* South Korea */
+	CTRY_KOREA_ROC2           = 411,     /* South Korea */
+	CTRY_KUWAIT               = 414,     /* Kuwait */
+	CTRY_LATVIA               = 428,     /* Latvia */
+	CTRY_LEBANON              = 422,     /* Lebanon */
+	CTRY_LIBYA                = 434,     /* Libya */
+	CTRY_LIECHTENSTEIN        = 438,     /* Liechtenstein */
+	CTRY_LITHUANIA            = 440,     /* Lithuania */
+	CTRY_LUXEMBOURG           = 442,     /* Luxembourg */
+	CTRY_MACAU                = 446,     /* Macau */
+	CTRY_MACEDONIA            = 807,     /* the Former Yugoslav Republic of Macedonia */
+	CTRY_MALAYSIA             = 458,     /* Malaysia */
+	CTRY_MEXICO               = 484,     /* Mexico */
+	CTRY_MONACO               = 492,     /* Principality of Monaco */
+	CTRY_MOROCCO              = 504,     /* Morocco */
+	CTRY_NETHERLANDS          = 528,     /* Netherlands */
+	CTRY_NEW_ZEALAND          = 554,     /* New Zealand */
+	CTRY_NICARAGUA            = 558,     /* Nicaragua */
+	CTRY_NORWAY               = 578,     /* Norway */
+	CTRY_OMAN                 = 512,     /* Oman */
+	CTRY_PAKISTAN             = 586,     /* Islamic Republic of Pakistan */
+	CTRY_PANAMA               = 591,     /* Panama */
+	CTRY_PARAGUAY             = 600,     /* Paraguay */
+	CTRY_PERU                 = 604,     /* Peru */
+	CTRY_PHILIPPINES          = 608,     /* Republic of the Philippines */
+	CTRY_POLAND               = 616,     /* Poland */
+	CTRY_PORTUGAL             = 620,     /* Portugal */
+	CTRY_PUERTO_RICO          = 630,     /* Puerto Rico */
+	CTRY_QATAR                = 634,     /* Qatar */
+	CTRY_ROMANIA              = 642,     /* Romania */
+	CTRY_RUSSIA               = 643,     /* Russia */
+	CTRY_SAUDI_ARABIA         = 682,     /* Saudi Arabia */
+	CTRY_SINGAPORE            = 702,     /* Singapore */
+	CTRY_SLOVAKIA             = 703,     /* Slovak Republic */
+	CTRY_SLOVENIA             = 705,     /* Slovenia */
+	CTRY_SOUTH_AFRICA         = 710,     /* South Africa */
+	CTRY_SPAIN                = 724,     /* Spain */
+	CTRY_SWEDEN               = 752,     /* Sweden */
+	CTRY_SWITZERLAND          = 756,     /* Switzerland */
+	CTRY_SYRIA                = 760,     /* Syria */
+	CTRY_TAIWAN               = 158,     /* Taiwan */
+	CTRY_THAILAND             = 764,     /* Thailand */
+	CTRY_TRINIDAD_Y_TOBAGO    = 780,     /* Trinidad y Tobago */
+	CTRY_TUNISIA              = 788,     /* Tunisia */
+	CTRY_TURKEY               = 792,     /* Turkey */
+	CTRY_UAE                  = 784,     /* U.A.E. */
+	CTRY_UKRAINE              = 804,     /* Ukraine */
+	CTRY_UNITED_KINGDOM       = 826,     /* United Kingdom */
+	CTRY_UNITED_STATES        = 840,     /* United States */
+	CTRY_UNITED_STATES_FCC49  = 842,     /* United States (Public Safety)*/
+	CTRY_URUGUAY              = 858,     /* Uruguay */
+	CTRY_UZBEKISTAN           = 860,     /* Uzbekistan */
+	CTRY_VENEZUELA            = 862,     /* Venezuela */
+	CTRY_VIET_NAM             = 704,     /* Viet Nam */
+	CTRY_YEMEN                = 887,     /* Yemen */
+	CTRY_ZIMBABWE             = 716      /* Zimbabwe */
+};
+
+/* 
+ * Generic information element
+ */
+struct ieee80211_ie {
+	u_int8_t id;
+	u_int8_t len;
+	u_int8_t info[0];
+} __packed;
+
+/* 
+ * Country information element.
+ */
+#define IEEE80211_COUNTRY_MAX_TRIPLETS (83)
+struct ieee80211_ie_country {
+	u_int8_t country_id;
+	u_int8_t country_len;
+	u_int8_t country_str[3];
+	u_int8_t country_triplet[IEEE80211_COUNTRY_MAX_TRIPLETS * 3];
+} __packed;
+
+/*
+ * Power Constraint information element.
+ */
+struct ieee80211_ie_pwrcnstr {
+	u_int8_t pc_id;			/* IEEE80211_ELEMID_PWRCNSTR */
+	u_int8_t pc_len;		/* == 2 */
+	u_int8_t pc_lpc;		/* Local Power Constraint [dB] */
+} __packed;
+
+/*
+ * Power Capability information element.
+ */
+struct ieee80211_ie_pwrcap {
+	u_int8_t pc_id;			/* IEEE80211_ELEMID_PWRCAP */
+	u_int8_t pc_len;		/* == 2 */
+	int8_t pc_mintxpow;		/* Minimum Transmit Power Capability [dBm] */
+	int8_t pc_maxtxpow;		/* Maximum Transmit Power Capability [dBm] */
+} __packed;
+
+/*
+ * Supported Channels information element.
+ */
+#define IEEE80211_SUPPCHAN_MAX_PAIRS (127)
+struct ieee80211_ie_sc {
+	u_int8_t sc_id;			/* IEEE80211_ELEMID_SUPPCHAN */
+	u_int8_t sc_len;		/* == 2 * number of sc_subband elements */
+	struct {
+		u_int8_t sc_first;	/* First Channel Number */
+		u_int8_t sc_number;	/* Number of Channels */
+	} __packed sc_subband[IEEE80211_SUPPCHAN_MAX_PAIRS];
+} __packed;
+
+/*
+ * Channel Switch Announcement information element.
+ */
+struct ieee80211_ie_csa {
+	u_int8_t csa_id;	/* IEEE80211_ELEMID_CHANSWITCHANN */
+	u_int8_t csa_len;	/* == 3 */
+	u_int8_t csa_mode;	/* Channel Switch Mode: 1 == stop transmission until CS */
+	u_int8_t csa_chan;	/* New Channel Number */
+	u_int8_t csa_count;	/* TBTTs until Channel Switch happens */
+} __packed;
+
+/* minimal Channel Switch Count in the initial announcement */
+#define IEEE80211_CSA_PROTECTION_PERIOD 3
+
+/* maximum allowed deviance of measurement of intervals between CSA in Beacons */
+#define IEEE80211_CSA_SANITY_THRESHOLD 100
+
+
+/* does frame have QoS sequence control data */
+#define	IEEE80211_QOS_HAS_SEQ(wh) \
+	(((wh)->i_fc[0] & \
+	  (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \
+	  (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
+
+#define WME_QOSINFO_COUNT	0x0f  /* Mask for Param Set Count field */
+/*
+ * WME/802.11e information element.
+ */
+struct ieee80211_ie_wme {
+	u_int8_t wme_id;		/* IEEE80211_ELEMID_VENDOR */
+	u_int8_t wme_len;	/* length in bytes */
+	u_int8_t wme_oui[3];	/* 0x00, 0x50, 0xf2 */
+	u_int8_t wme_type;	/* OUI type */
+	u_int8_t wme_subtype;	/* OUI subtype */
+	u_int8_t wme_version;	/* spec revision */
+	u_int8_t wme_info;	/* QoS info */
+} __packed;
+
+/*
+ * WME/802.11e Tspec Element
+ */
+struct ieee80211_wme_tspec {
+	u_int8_t ts_id;
+	u_int8_t ts_len;
+	u_int8_t ts_oui[3];
+	u_int8_t ts_oui_type;
+	u_int8_t ts_oui_subtype;
+	u_int8_t ts_version;
+	u_int8_t ts_tsinfo[3];
+	u_int8_t ts_nom_msdu[2];
+	u_int8_t ts_max_msdu[2];
+	u_int8_t ts_min_svc[4];
+	u_int8_t ts_max_svc[4];
+	u_int8_t ts_inactv_intv[4];
+	u_int8_t ts_susp_intv[4];
+	u_int8_t ts_start_svc[4];
+	u_int8_t ts_min_rate[4];
+	u_int8_t ts_mean_rate[4];
+	u_int8_t ts_max_burst[4];
+	u_int8_t ts_min_phy[4];
+	u_int8_t ts_peak_rate[4];
+	u_int8_t ts_delay[4];
+	u_int8_t ts_surplus[2];
+	u_int8_t ts_medium_time[2];
+} __packed;
+
+/*
+ * WME AC parameter field
+ */
+
+struct ieee80211_wme_acparams {
+	u_int8_t acp_aci_aifsn;
+	u_int8_t acp_logcwminmax;
+	u_int16_t acp_txop;
+} __packed;
+
+#define IEEE80211_WME_PARAM_LEN 24
+#define WME_NUM_AC		4	/* 4 AC categories */
+
+#define WME_PARAM_ACI		0x60	/* Mask for ACI field */
+#define WME_PARAM_ACI_S		5	/* Shift for ACI field */
+#define WME_PARAM_ACM		0x10	/* Mask for ACM bit */
+#define WME_PARAM_ACM_S		4	/* Shift for ACM bit */
+#define WME_PARAM_AIFSN		0x0f	/* Mask for aifsn field */
+#define WME_PARAM_AIFSN_S	0	/* Shift for aifsn field */
+#define WME_PARAM_LOGCWMIN	0x0f	/* Mask for CwMin field (in log) */
+#define WME_PARAM_LOGCWMIN_S	0	/* Shift for CwMin field */
+#define WME_PARAM_LOGCWMAX	0xf0	/* Mask for CwMax field (in log) */
+#define WME_PARAM_LOGCWMAX_S	4	/* Shift for CwMax field */
+
+#define WME_AC_TO_TID(_ac) (       \
+	((_ac) == WME_AC_VO) ? 6 : \
+	((_ac) == WME_AC_VI) ? 5 : \
+	((_ac) == WME_AC_BK) ? 1 : \
+	0)
+
+#define TID_TO_WME_AC(_tid) (      \
+	((_tid) < 1) ? WME_AC_BE : \
+	((_tid) < 3) ? WME_AC_BK : \
+	((_tid) < 6) ? WME_AC_VI : \
+	WME_AC_VO)
+
+/*
+ * WME Parameter Element
+ */
+
+struct ieee80211_wme_param {
+	u_int8_t param_id;
+	u_int8_t param_len;
+	u_int8_t param_oui[3];
+	u_int8_t param_oui_type;
+	u_int8_t param_oui_sybtype;
+	u_int8_t param_version;
+	u_int8_t param_qosInfo;
+	u_int8_t param_reserved;
+	struct ieee80211_wme_acparams	params_acParams[WME_NUM_AC];
+} __packed;
+
+/*
+ * WME U-APSD qos info field defines
+ */
+#define WME_CAPINFO_UAPSD_EN			0x00000080
+#define WME_CAPINFO_UAPSD_VO			0x00000001
+#define WME_CAPINFO_UAPSD_VI			0x00000002
+#define WME_CAPINFO_UAPSD_BK			0x00000004
+#define WME_CAPINFO_UAPSD_BE			0x00000008
+#define WME_CAPINFO_UAPSD_ACFLAGS_SHIFT		0
+#define WME_CAPINFO_UAPSD_ACFLAGS_MASK		0xF
+#define WME_CAPINFO_UAPSD_MAXSP_SHIFT		5
+#define WME_CAPINFO_UAPSD_MAXSP_MASK		0x3
+#define WME_CAPINFO_IE_OFFSET			8
+#define WME_UAPSD_MAXSP(_qosinfo)					\
+		(((_qosinfo) >> WME_CAPINFO_UAPSD_MAXSP_SHIFT) & 	\
+		 WME_CAPINFO_UAPSD_MAXSP_MASK)
+#define WME_UAPSD_AC_ENABLED(_ac, _qosinfo)				\
+		((1 << (3 - (_ac))) & (					\
+		 ((_qosinfo) >> WME_CAPINFO_UAPSD_ACFLAGS_SHIFT) &	\
+		 WME_CAPINFO_UAPSD_ACFLAGS_MASK))
+
+/*
+ * Atheros Advanced Capability information element.
+ */
+struct ieee80211_ie_athAdvCap {
+	u_int8_t athAdvCap_id;		/* IEEE80211_ELEMID_VENDOR */
+	u_int8_t athAdvCap_len;		/* length in bytes */
+	u_int8_t athAdvCap_oui[3];	/* 0x00, 0x03, 0x7f */
+	u_int8_t athAdvCap_type;	/* OUI type */
+	u_int8_t athAdvCap_subtype;	/* OUI subtype */
+	u_int8_t athAdvCap_version;	/* spec revision */
+	u_int8_t athAdvCap_capability;	/* Capability info */
+	u_int16_t athAdvCap_defKeyIndex;
+} __packed;
+
+/*
+ * Atheros XR information element.
+ */
+struct ieee80211_xr_param {
+	u_int8_t param_id;
+	u_int8_t param_len;
+	u_int8_t param_oui[3];
+	u_int8_t param_oui_type;
+	u_int8_t param_oui_sybtype;
+	u_int8_t param_version;
+	u_int8_t param_Info;
+	u_int8_t param_base_bssid[IEEE80211_ADDR_LEN];
+	u_int8_t param_xr_bssid[IEEE80211_ADDR_LEN];
+	u_int16_t param_xr_beacon_interval;
+	u_int8_t param_base_ath_capability;
+	u_int8_t param_xr_ath_capability;
+} __packed;
+
+/* Atheros capabilities */
+#define IEEE80211_ATHC_TURBOP	0x0001		/* Turbo Prime */
+#define IEEE80211_ATHC_COMP	0x0002		/* Compression */
+#define IEEE80211_ATHC_FF	0x0004		/* Fast Frames */
+#define IEEE80211_ATHC_XR	0x0008		/* Xtended Range support */
+#define IEEE80211_ATHC_AR	0x0010		/* Advanced Radar support */
+#define IEEE80211_ATHC_BURST	0x0020		/* Bursting - not negotiated */
+#define IEEE80211_ATHC_WME	0x0040		/* CWMin tuning */
+#define IEEE80211_ATHC_BOOST	0x0080		/* Boost */
+
+/*
+ * Management Notification Frame
+ */
+struct ieee80211_mnf {
+	u_int8_t mnf_category;
+	u_int8_t mnf_action;
+	u_int8_t mnf_dialog;
+	u_int8_t mnf_status;
+} __packed;
+#define	MNF_SETUP_REQ	0
+#define	MNF_SETUP_RESP	1
+#define	MNF_TEARDOWN	2
+
+/*
+ * Control frames.
+ */
+struct ieee80211_frame_min {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+	u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+	/* FCS */
+} __packed;
+
+struct ieee80211_frame_rts {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_ra[IEEE80211_ADDR_LEN];
+	u_int8_t i_ta[IEEE80211_ADDR_LEN];
+	/* FCS */
+} __packed;
+
+struct ieee80211_frame_cts {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_ra[IEEE80211_ADDR_LEN];
+	/* FCS */
+} __packed;
+
+struct ieee80211_frame_ack {
+	u_int8_t i_fc[2];
+	__le16 i_dur;
+	u_int8_t i_ra[IEEE80211_ADDR_LEN];
+	/* FCS */
+} __packed;
+
+struct ieee80211_frame_pspoll {
+	u_int8_t i_fc[2];
+	u_int8_t i_aid[2];
+	u_int8_t i_bssid[IEEE80211_ADDR_LEN];
+	u_int8_t i_ta[IEEE80211_ADDR_LEN];
+	/* FCS */
+} __packed;
+
+struct ieee80211_frame_cfend {		/* NB: also CF-End+CF-Ack */
+	u_int8_t i_fc[2];
+	__le16 i_dur;	/* should be zero */
+	u_int8_t i_ra[IEEE80211_ADDR_LEN];
+	u_int8_t i_bssid[IEEE80211_ADDR_LEN];
+	/* FCS */
+} __packed;
+
+/*
+ * BEACON management packets
+ *
+ *	octet timestamp[8]
+ *	octet beacon interval[2]
+ *	octet capability information[2]
+ *	information element
+ *		octet elemid
+ *		octet length
+ *		octet information[length]
+ */
+
+typedef u_int8_t *ieee80211_mgt_beacon_t;
+
+#define	IEEE80211_BEACON_INTERVAL(beacon) \
+	((beacon)[8] | ((beacon)[9] << 8))
+#define	IEEE80211_BEACON_CAPABILITY(beacon) \
+	((beacon)[10] | ((beacon)[11] << 8))
+
+#define	IEEE80211_CAPINFO_ESS			0x0001
+#define	IEEE80211_CAPINFO_IBSS			0x0002
+#define	IEEE80211_CAPINFO_CF_POLLABLE		0x0004
+#define	IEEE80211_CAPINFO_CF_POLLREQ		0x0008
+#define	IEEE80211_CAPINFO_PRIVACY		0x0010
+#define	IEEE80211_CAPINFO_SHORT_PREAMBLE	0x0020
+#define	IEEE80211_CAPINFO_PBCC			0x0040
+#define	IEEE80211_CAPINFO_CHNL_AGILITY		0x0080
+/* bits 8-9 are reserved (8 now for spectrum management) */
+#define IEEE80211_CAPINFO_SPECTRUM_MGMT		0x0100
+#define	IEEE80211_CAPINFO_SHORT_SLOTTIME	0x0400
+#define	IEEE80211_CAPINFO_RSN			0x0800
+/* bit 12 is reserved */
+#define	IEEE80211_CAPINFO_DSSSOFDM		0x2000
+/* bits 14-15 are reserved */
+
+/*
+ * 802.11i/WPA information element (maximally sized).
+ */
+struct ieee80211_ie_wpa {
+	u_int8_t wpa_id;			/* IEEE80211_ELEMID_VENDOR */
+	u_int8_t wpa_len;		/* length in bytes */
+	u_int8_t wpa_oui[3];		/* 0x00, 0x50, 0xf2 */
+	u_int8_t wpa_type;		/* OUI type */
+	u_int16_t wpa_version;		/* spec revision */
+	u_int32_t wpa_mcipher[1];	/* multicast/group key cipher */
+	u_int16_t wpa_uciphercnt;	/* # pairwise key ciphers */
+	u_int32_t wpa_uciphers[8];	/* ciphers */
+	u_int16_t wpa_authselcnt;	/* authentication selector cnt*/
+	u_int32_t wpa_authsels[8];	/* selectors */
+	u_int16_t wpa_caps;		/* 802.11i capabilities */
+	u_int16_t wpa_pmkidcnt;		/* 802.11i pmkid count */
+	u_int16_t wpa_pmkids[8];	/* 802.11i pmkids */
+} __packed;
+
+/*
+ * Management information element payloads.
+ */
+
+enum {
+	IEEE80211_ELEMID_SSID		= 0,
+	IEEE80211_ELEMID_RATES		= 1,
+	IEEE80211_ELEMID_FHPARMS	= 2,
+	IEEE80211_ELEMID_DSPARMS	= 3,
+	IEEE80211_ELEMID_CFPARMS	= 4,
+	IEEE80211_ELEMID_TIM		= 5,
+	IEEE80211_ELEMID_IBSSPARMS	= 6,
+	IEEE80211_ELEMID_COUNTRY	= 7,
+	IEEE80211_ELEMID_HOPPATRNPARMS  = 8,
+	IEEE80211_ELEMID_HOPPATRNTABLE  = 9,
+	IEEE80211_ELEMID_REQINFO	= 10,
+	IEEE80211_ELEMID_QBSSLOAD       = 11,
+	IEEE80211_ELEMID_EDCAPARAM      = 12,
+	IEEE80211_ELEMID_TSPEC		= 13,
+	IEEE80211_ELEMID_TRAFCLASS      = 14,
+	IEEE80211_ELEMID_SCHEDULE       = 15,
+	IEEE80211_ELEMID_CHALLENGE	= 16,
+	/* 17-31 reserved for challenge text extension */
+	IEEE80211_ELEMID_PWRCNSTR	= 32,
+	IEEE80211_ELEMID_PWRCAP		= 33,
+	IEEE80211_ELEMID_TPCREQ		= 34,
+	IEEE80211_ELEMID_TPCREP		= 35,
+	IEEE80211_ELEMID_SUPPCHAN	= 36,
+	IEEE80211_ELEMID_CHANSWITCHANN	= 37,
+	IEEE80211_ELEMID_MEASREQ	= 38,
+	IEEE80211_ELEMID_MEASREP	= 39,
+	IEEE80211_ELEMID_QUIET		= 40,
+	IEEE80211_ELEMID_IBSSDFS	= 41,
+	IEEE80211_ELEMID_ERP		= 42,
+	IEEE80211_ELEMID_TSDELAY	= 43,
+	IEEE80211_ELEMID_TCLASSPROC     = 44,
+	IEEE80211_ELEMID_QOS		= 46,
+	IEEE80211_ELEMID_RSN		= 48,
+	/* 49 reserved */
+	IEEE80211_ELEMID_XRATES		= 50,
+	/* 128-129 proprietary elements used by Agere chipsets */
+	IEEE80211_ELEMID_AGERE1		= 128,
+	IEEE80211_ELEMID_AGERE2		= 129,
+	IEEE80211_ELEMID_TPC		= 150,
+	IEEE80211_ELEMID_CCKM		= 156,
+	IEEE80211_ELEMID_VENDOR		= 221,	/* vendor private */
+};
+
+#define IEEE80211_CHANSWITCHANN_BYTES 	5
+#define BITCTL_BUFD_MCAST       	1
+#define BITCTL_BUFD_UCAST_AID_MASK 	((u_int8_t)~(BITCTL_BUFD_MCAST))
+#define BITCTL_BUFD_UCAST_AID_SHIFT 	1
+
+struct ieee80211_tim_ie {
+	u_int8_t	tim_ie;			/* IEEE80211_ELEMID_TIM */
+	u_int8_t	tim_len;
+	u_int8_t	tim_count;		/* DTIM count */
+	u_int8_t	tim_period;		/* DTIM period */
+	u_int8_t	tim_bitctl;		/* bitmap control */
+	u_int8_t	tim_bitmap[1];		/* variable-length bitmap */
+} __packed;
+
+struct ieee80211_country_ie {
+	u_int8_t	ie;			/* IEEE80211_ELEMID_COUNTRY */
+	u_int8_t	len;
+	u_int8_t	cc[3];			/* ISO CC+(I)ndoor/(O)utdoor */
+	struct {
+		u_int8_t schan;			/* starting channel */
+		u_int8_t nchan;			/* number channels */
+		u_int8_t maxtxpwr;		/* tx power cap */
+	} __packed band[4];			/* up to 4 sub bands */
+} __packed;
+
+#define IEEE80211_CHALLENGE_LEN		128
+
+#define IEEE80211_SUPPCHAN_LEN		26
+
+#define	IEEE80211_RATE_BASIC		0x80
+#define	IEEE80211_RATE_VAL		0x7f
+
+/* EPR information element flags */
+#define	IEEE80211_ERP_NON_ERP_PRESENT	0x01
+#define	IEEE80211_ERP_USE_PROTECTION	0x02
+#define	IEEE80211_ERP_LONG_PREAMBLE	0x04
+
+/* Atheros private advanced capabilities info */
+#define	ATHEROS_CAP_TURBO_PRIME		0x01
+#define	ATHEROS_CAP_COMPRESSION		0x02
+#define	ATHEROS_CAP_FAST_FRAME		0x04
+/* bits 3-6 reserved */
+#define	ATHEROS_CAP_BOOST		0x80
+
+#define	ATH_OUI			0x7f0300		/* Atheros OUI */
+#define	ATH_OUI_TYPE		0x01
+#define	ATH_OUI_SUBTYPE		0x01
+#define	ATH_OUI_VERSION		0x00
+#define	ATH_OUI_TYPE_XR		0x03
+#define	ATH_OUI_SUBTYPE_XR	0x01
+#define	ATH_OUI_VER_XR		0x00
+
+#define	WPA_OUI			0xf25000
+#define	WPA_OUI_TYPE		0x01
+#define	WPA_VERSION		1		/* current supported version */
+
+#define	WPA_CSE_NULL		0x00
+#define	WPA_CSE_WEP40		0x01
+#define	WPA_CSE_TKIP		0x02
+#define	WPA_CSE_CCMP		0x04
+#define	WPA_CSE_WEP104		0x05
+
+#define	WPA_ASE_NONE		0x00
+#define	WPA_ASE_8021X_UNSPEC	0x01
+#define	WPA_ASE_8021X_PSK	0x02
+
+#define	RSN_OUI			0xac0f00
+#define	RSN_VERSION		1		/* current supported version */
+
+#define	RSN_CSE_NULL		0x00
+#define	RSN_CSE_WEP40		0x01
+#define	RSN_CSE_TKIP		0x02
+#define	RSN_CSE_WRAP		0x03
+#define	RSN_CSE_CCMP		0x04
+#define	RSN_CSE_WEP104		0x05
+
+#define	RSN_ASE_NONE		0x00
+#define	RSN_ASE_8021X_UNSPEC	0x01
+#define	RSN_ASE_8021X_PSK	0x02
+
+#define	RSN_CAP_PREAUTH		0x01
+
+#define	WME_OUI			0xf25000
+#define	WME_OUI_TYPE		0x02
+#define	WME_INFO_OUI_SUBTYPE	0x00
+#define	WME_PARAM_OUI_SUBTYPE	0x01
+#define	WME_VERSION		1
+
+/* WME stream classes */
+#define	WME_AC_BE	0		/* best effort */
+#define	WME_AC_BK	1		/* background */
+#define	WME_AC_VI	2		/* video */
+#define	WME_AC_VO	3		/* voice */
+
+/*
+ * AUTH management packets
+ *
+ *	octet algo[2]
+ *	octet seq[2]
+ *	octet status[2]
+ *	octet chal.id
+ *	octet chal.length
+ *	octet chal.text[253]
+ */
+
+typedef u_int8_t *ieee80211_mgt_auth_t;
+
+#define	IEEE80211_AUTH_ALGORITHM(auth) \
+	((auth)[0] | ((auth)[1] << 8))
+#define	IEEE80211_AUTH_TRANSACTION(auth) \
+	((auth)[2] | ((auth)[3] << 8))
+#define	IEEE80211_AUTH_STATUS(auth) \
+	((auth)[4] | ((auth)[5] << 8))
+
+#define	IEEE80211_AUTH_ALG_OPEN		0x0000
+#define	IEEE80211_AUTH_ALG_SHARED	0x0001
+#define	IEEE80211_AUTH_ALG_LEAP		0x0080
+
+enum {
+	IEEE80211_AUTH_OPEN_REQUEST		= 1,
+	IEEE80211_AUTH_OPEN_RESPONSE		= 2,
+};
+
+enum {
+	IEEE80211_AUTH_SHARED_REQUEST		= 1,
+	IEEE80211_AUTH_SHARED_CHALLENGE		= 2,
+	IEEE80211_AUTH_SHARED_RESPONSE		= 3,
+	IEEE80211_AUTH_SHARED_PASS		= 4,
+};
+
+/*
+ * Reason codes
+ *
+ * Unlisted codes are reserved
+ */
+
+enum {
+	IEEE80211_REASON_UNSPECIFIED		= 1,
+	IEEE80211_REASON_AUTH_EXPIRE		= 2,
+	IEEE80211_REASON_AUTH_LEAVE		= 3,
+	IEEE80211_REASON_ASSOC_EXPIRE		= 4,
+	IEEE80211_REASON_ASSOC_TOOMANY		= 5,
+	IEEE80211_REASON_NOT_AUTHED		= 6,
+	IEEE80211_REASON_NOT_ASSOCED		= 7,
+	IEEE80211_REASON_ASSOC_LEAVE		= 8,
+	IEEE80211_REASON_ASSOC_NOT_AUTHED	= 9,
+
+	IEEE80211_REASON_PWRCAP_UNACCEPTABLE	= 10,
+	IEEE80211_REASON_SUPPCHAN_UNACCEPTABLE	= 11,
+	IEEE80211_REASON_RSN_REQUIRED		= 11,
+	IEEE80211_REASON_RSN_INCONSISTENT	= 12,
+	IEEE80211_REASON_IE_INVALID		= 13,
+	IEEE80211_REASON_MIC_FAILURE		= 14,
+
+	IEEE80211_STATUS_SUCCESS		= 0,
+	IEEE80211_STATUS_UNSPECIFIED		= 1,
+	IEEE80211_STATUS_CAPINFO		= 10,
+	IEEE80211_STATUS_NOT_ASSOCED		= 11,
+	IEEE80211_STATUS_OTHER			= 12,
+	IEEE80211_STATUS_ALG			= 13,
+	IEEE80211_STATUS_SEQUENCE		= 14,
+	IEEE80211_STATUS_CHALLENGE		= 15,
+	IEEE80211_STATUS_TIMEOUT		= 16,
+	IEEE80211_STATUS_TOOMANY		= 17,
+	IEEE80211_STATUS_BASIC_RATE		= 18,
+	IEEE80211_STATUS_SP_REQUIRED		= 19,
+	IEEE80211_STATUS_PBCC_REQUIRED		= 20,
+	IEEE80211_STATUS_CA_REQUIRED		= 21,
+	IEEE80211_STATUS_SM_REQUIRED		= 22,
+	IEEE80211_STATUS_PWRCAP_UNACCEPTABLE	= 23,
+	IEEE80211_STATUS_SUPPCHAN_UNACCEPTABLE	= 24,
+	IEEE80211_STATUS_TOO_MANY_STATIONS	= 22,
+	IEEE80211_STATUS_RATES			= 23,
+	IEEE80211_STATUS_SHORTSLOT_REQUIRED	= 25,
+	IEEE80211_STATUS_DSSSOFDM_REQUIRED	= 26,
+};
+
+#define	IEEE80211_WEP_KEYLEN		5	/* 40bit */
+#define	IEEE80211_WEP_IVLEN		3	/* 24bit */
+#define	IEEE80211_WEP_KIDLEN		1	/* 1 octet */
+#define	IEEE80211_WEP_CRCLEN		4	/* CRC-32 */
+#define	IEEE80211_WEP_NKID		4	/* number of key ids */
+
+/*
+ * 802.11i defines an extended IV for use with non-WEP ciphers.
+ * When the EXTIV bit is set in the key id byte an additional
+ * 4 bytes immediately follow the IV for TKIP.  For CCMP the
+ * EXTIV bit is likewise set but the 8 bytes represent the
+ * CCMP header rather than IV+extended-IV.
+ */
+#define	IEEE80211_WEP_EXTIV		0x20
+#define	IEEE80211_WEP_EXTIVLEN		4	/* extended IV length */
+#define	IEEE80211_WEP_MICLEN		8	/* trailing MIC */
+
+#define	IEEE80211_CRC_LEN		4
+
+/*
+ * Maximum acceptable MTU is:
+ *	IEEE80211_MAX_LEN - WEP overhead - CRC -
+ *		QoS overhead - RSN/WPA overhead
+ * Min is arbitrarily chosen > IEEE80211_MIN_LEN.  The default
+ * mtu is Ethernet-compatible; it's set by ether_ifattach.
+ */
+#define	IEEE80211_MTU_MAX		2290
+#define	IEEE80211_MTU_MIN		32
+
+#define	IEEE80211_MAX_LEN		(2300 + IEEE80211_CRC_LEN + \
+	(IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))
+#define	IEEE80211_ACK_LEN \
+	(sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN)
+#define	IEEE80211_MIN_LEN \
+	(sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN)
+
+/*
+ * The 802.11 spec says at most 2007 stations may be
+ * associated at once.  For most APs this is way more
+ * than is feasible so we use a default of 128.  This
+ * number may be overridden by the driver and/or by
+ * user configuration.
+ */
+#define	IEEE80211_AID_MAX		2007
+#define	IEEE80211_AID_DEF		128
+
+#define	IEEE80211_AID(b)	((b) &~ 0xc000)
+
+/* 
+ * RTS frame length parameters.  The default is specified in
+ * the 802.11 spec.  The max may be wrong for jumbo frames.
+ */
+#define	IEEE80211_RTS_DEFAULT		512
+#define	IEEE80211_RTS_MIN		1
+#define	IEEE80211_RTS_MAX		2346
+
+/* 
+ * Regulatory extension identifier for country IE.
+ */
+#define IEEE80211_REG_EXT_ID		201
+
+/*
+ * IEEE 802.11 timer synchronization function (TSF) timestamp length
+ */
+#define IEEE80211_TSF_LEN		8
+
+#endif /* _NET80211_IEEE80211_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_ioctl.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_ioctl.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_ioctl.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_ioctl.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,707 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_ioctl.h 3314 2008-01-30 23:50:16Z mtaylor $
+ */
+#ifndef _NET80211_IEEE80211_IOCTL_H_
+#define _NET80211_IEEE80211_IOCTL_H_
+
+/*
+ * IEEE 802.11 ioctls.
+ */
+#include <net80211/_ieee80211.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+
+/*
+ * Per/node (station) statistics available when operating as an AP.
+ */
+struct ieee80211_nodestats {
+	u_int32_t ns_rx_data;		/* rx data frames */
+	u_int32_t ns_rx_mgmt;		/* rx management frames */
+	u_int32_t ns_rx_ctrl;		/* rx control frames */
+	u_int32_t ns_rx_ucast;		/* rx unicast frames */
+	u_int32_t ns_rx_mcast;		/* rx multi/broadcast frames */
+	u_int64_t ns_rx_bytes;		/* rx data count (bytes) */
+	u_int64_t ns_rx_beacons;		/* rx beacon frames */
+	u_int32_t ns_rx_proberesp;	/* rx probe response frames */
+
+	u_int32_t ns_rx_dup;		/* rx discard because it's a dup */
+	u_int32_t ns_rx_noprivacy;	/* rx w/ wep but privacy off */
+	u_int32_t ns_rx_wepfail;		/* rx wep processing failed */
+	u_int32_t ns_rx_demicfail;	/* rx demic failed */
+	u_int32_t ns_rx_decap;		/* rx decapsulation failed */
+	u_int32_t ns_rx_defrag;		/* rx defragmentation failed */
+	u_int32_t ns_rx_disassoc;	/* rx disassociation */
+	u_int32_t ns_rx_deauth;		/* rx deauthentication */
+	u_int32_t ns_rx_decryptcrc;	/* rx decrypt failed on crc */
+	u_int32_t ns_rx_unauth;		/* rx on unauthorized port */
+	u_int32_t ns_rx_unencrypted;	/* rx unecrypted w/ privacy */
+
+	u_int32_t ns_tx_data;		/* tx data frames */
+	u_int32_t ns_tx_mgmt;		/* tx management frames */
+	u_int32_t ns_tx_ucast;		/* tx unicast frames */
+	u_int32_t ns_tx_mcast;		/* tx multi/broadcast frames */
+	u_int64_t ns_tx_bytes;		/* tx data count (bytes) */
+	u_int32_t ns_tx_probereq;	/* tx probe request frames */
+	u_int32_t ns_tx_uapsd;		/* tx on uapsd queue */
+
+	u_int32_t ns_tx_novlantag;	/* tx discard due to no tag */
+	u_int32_t ns_tx_vlanmismatch;	/* tx discard due to of bad tag */
+
+	u_int32_t ns_tx_eosplost;	/* uapsd EOSP retried out */
+
+	u_int32_t ns_ps_discard;		/* ps discard due to of age */
+
+	u_int32_t ns_uapsd_triggers;	/* uapsd triggers */
+
+	/* MIB-related state */
+	u_int32_t ns_tx_assoc;		/* [re]associations */
+	u_int32_t ns_tx_assoc_fail;	/* [re]association failures */
+	u_int32_t ns_tx_auth;		/* [re]authentications */
+	u_int32_t ns_tx_auth_fail;	/* [re]authentication failures*/
+	u_int32_t ns_tx_deauth;		/* deauthentications */
+	u_int32_t ns_tx_deauth_code;	/* last deauth reason */
+	u_int32_t ns_tx_disassoc;	/* disassociations */
+	u_int32_t ns_tx_disassoc_code;	/* last disassociation reason */
+	u_int32_t ns_psq_drops;		/* power save queue drops */
+};
+
+/*
+ * Summary statistics.
+ */
+struct ieee80211_stats {
+	u_int32_t is_rx_badversion;	/* rx frame with bad version */
+	u_int32_t is_rx_tooshort;	/* rx frame too short */
+	u_int32_t is_rx_wrongbss;	/* rx from wrong bssid */
+	u_int32_t is_rx_dup;		/* rx discard due to it's a dup */
+	u_int32_t is_rx_wrongdir;	/* rx w/ wrong direction */
+	u_int32_t is_rx_mcastecho;	/* rx discard due to of mcast echo */
+	u_int32_t is_rx_mcastdisabled;	/* rx discard due to of mcast disabled */
+	u_int32_t is_rx_notassoc;	/* rx discard due to sta !assoc */
+	u_int32_t is_rx_noprivacy;	/* rx w/ wep but privacy off */
+	u_int32_t is_rx_unencrypted;	/* rx w/o wep and privacy on */
+	u_int32_t is_rx_wepfail;		/* rx wep processing failed */
+	u_int32_t is_rx_decap;		/* rx decapsulation failed */
+	u_int32_t is_rx_mgtdiscard;	/* rx discard mgt frames */
+	u_int32_t is_rx_ctl;		/* rx discard ctrl frames */
+	u_int32_t is_rx_beacon;		/* rx beacon frames */
+	u_int32_t is_rx_rstoobig;	/* rx rate set truncated */
+	u_int32_t is_rx_elem_missing;	/* rx required element missing*/
+	u_int32_t is_rx_elem_toobig;	/* rx element too big */
+	u_int32_t is_rx_elem_toosmall;	/* rx element too small */
+	u_int32_t is_rx_elem_unknown;	/* rx element unknown */
+	u_int32_t is_rx_badchan;		/* rx frame w/ invalid chan */
+	u_int32_t is_rx_chanmismatch;	/* rx frame chan mismatch */
+	u_int32_t is_rx_nodealloc;	/* rx frame dropped */
+	u_int32_t is_rx_ssidmismatch;	/* rx frame ssid mismatch  */
+	u_int32_t is_rx_auth_unsupported;/* rx w/ unsupported auth alg */
+	u_int32_t is_rx_auth_fail;	/* rx sta auth failure */
+	u_int32_t is_rx_auth_countermeasures;/* rx auth discard due to CM */
+	u_int32_t is_rx_assoc_bss;	/* rx assoc from wrong bssid */
+	u_int32_t is_rx_assoc_notauth;	/* rx assoc w/o auth */
+	u_int32_t is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */
+	u_int32_t is_rx_assoc_norate;	/* rx assoc w/ no rate match */
+	u_int32_t is_rx_assoc_badwpaie;	/* rx assoc w/ bad WPA IE */
+	u_int32_t is_rx_assoc_badscie;	/* rx assoc w/ bad SC IE */
+	u_int32_t is_rx_deauth;		/* rx deauthentication */
+	u_int32_t is_rx_disassoc;	/* rx disassociation */
+	u_int32_t is_rx_badsubtype;	/* rx frame w/ unknown subtype*/
+	u_int32_t is_rx_nobuf;		/* rx failed for lack of buf */
+	u_int32_t is_rx_decryptcrc;	/* rx decrypt failed on crc */
+	u_int32_t is_rx_ahdemo_mgt;	/* rx discard ahdemo mgt frame*/
+	u_int32_t is_rx_bad_auth;	/* rx bad auth request */
+	u_int32_t is_rx_unauth;		/* rx on unauthorized port */
+	u_int32_t is_rx_badkeyid;	/* rx w/ incorrect keyid */
+	u_int32_t is_rx_ccmpreplay;	/* rx seq# violation (CCMP) */
+	u_int32_t is_rx_ccmpformat;	/* rx format bad (CCMP) */
+	u_int32_t is_rx_ccmpmic;		/* rx MIC check failed (CCMP) */
+	u_int32_t is_rx_tkipreplay;	/* rx seq# violation (TKIP) */
+	u_int32_t is_rx_tkipformat;	/* rx format bad (TKIP) */
+	u_int32_t is_rx_tkipmic;		/* rx MIC check failed (TKIP) */
+	u_int32_t is_rx_tkipicv;		/* rx ICV check failed (TKIP) */
+	u_int32_t is_rx_badcipher;	/* rx failed due to of key type */
+	u_int32_t is_rx_nocipherctx;	/* rx failed due to key !setup */
+	u_int32_t is_rx_acl;		/* rx discard due to of acl policy */
+	u_int32_t is_rx_ffcnt;		/* rx fast frames */
+	u_int32_t is_rx_badathtnl;   	/* driver key alloc failed */
+	u_int32_t is_tx_nobuf;		/* tx failed for lack of buf */
+	u_int32_t is_tx_nonode;		/* tx failed for no node */
+	u_int32_t is_tx_unknownmgt;	/* tx of unknown mgt frame */
+	u_int32_t is_tx_badcipher;	/* tx failed due to of key type */
+	u_int32_t is_tx_nodefkey;	/* tx failed due to no defkey */
+	u_int32_t is_tx_noheadroom;	/* tx failed due to no space */
+	u_int32_t is_tx_ffokcnt;		/* tx fast frames sent success */
+	u_int32_t is_tx_fferrcnt;	/* tx fast frames sent success */
+	u_int32_t is_scan_active;	/* active scans started */
+	u_int32_t is_scan_passive;	/* passive scans started */
+	u_int32_t is_node_timeout;	/* nodes timed out inactivity */
+	u_int32_t is_node_fdisassoc;	/* forced node disassociation */
+	u_int32_t is_crypto_nomem;	/* no memory for crypto ctx */
+	u_int32_t is_crypto_tkip;	/* tkip crypto done in s/w */
+	u_int32_t is_crypto_tkipenmic;	/* tkip en-MIC done in s/w */
+	u_int32_t is_crypto_tkipdemic;	/* tkip de-MIC done in s/w */
+	u_int32_t is_crypto_tkipcm;	/* tkip counter measures */
+	u_int32_t is_crypto_ccmp;	/* ccmp crypto done in s/w */
+	u_int32_t is_crypto_wep;		/* wep crypto done in s/w */
+	u_int32_t is_crypto_setkey_cipher;/* cipher rejected key */
+	u_int32_t is_crypto_setkey_nokey;/* no key index for setkey */
+	u_int32_t is_crypto_delkey;	/* driver key delete failed */
+	u_int32_t is_crypto_badcipher;	/* unknown cipher */
+	u_int32_t is_crypto_nocipher;	/* cipher not available */
+	u_int32_t is_crypto_attachfail;	/* cipher attach failed */
+	u_int32_t is_crypto_swfallback;	/* cipher fallback to s/w */
+	u_int32_t is_crypto_keyfail;	/* driver key alloc failed */
+	u_int32_t is_crypto_enmicfail;	/* en-MIC failed */
+	u_int32_t is_ibss_capmismatch;	/* merge failed-cap mismatch */
+	u_int32_t is_ibss_norate;	/* merge failed-rate mismatch */
+	u_int32_t is_ps_unassoc;		/* ps-poll for unassoc. sta */
+	u_int32_t is_ps_badaid;		/* ps-poll w/ incorrect aid */
+	u_int32_t is_ps_qempty;		/* ps-poll w/ nothing to send */
+};
+
+/*
+ * Max size of optional information elements.  We artificially
+ * constrain this; it's limited only by the max frame size (and
+ * the max parameter size of the wireless extensions).
+ */
+#define	IEEE80211_MAX_OPT_IE	256
+
+/*
+ * WPA/RSN get/set key request.  Specify the key/cipher
+ * type and whether the key is to be used for sending and/or
+ * receiving.  The key index should be set only when working
+ * with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
+ * Otherwise a unicast/pairwise key is specified by the bssid
+ * (on a station) or mac address (on an ap).  They key length
+ * must include any MIC key data; otherwise it should be no
+ more than IEEE80211_KEYBUF_SIZE.
+ */
+struct ieee80211req_key {
+	u_int8_t ik_type;		/* key/cipher type */
+	u_int8_t ik_pad;
+	ieee80211_keyix_t ik_keyix;	/* key index */
+	u_int8_t ik_keylen;		/* key length in bytes */
+	u_int8_t ik_flags;
+/* NB: IEEE80211_KEY_XMIT and IEEE80211_KEY_RECV defined elsewhere */
+#define	IEEE80211_KEY_DEFAULT	0x80	/* default xmit key */
+	u_int8_t ik_macaddr[IEEE80211_ADDR_LEN];
+	u_int64_t ik_keyrsc;		/* key receive sequence counter */
+	u_int64_t ik_keytsc;		/* key transmit sequence counter */
+	u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
+};
+
+/*
+ * Delete a key either by index or address.  Set the index
+ * to IEEE80211_KEYIX_NONE when deleting a unicast key.
+ */
+struct ieee80211req_del_key {
+	/* NB: This is different to ieee80211_keyix_t, but this is OK as 
+	 * values are unique over the low order bits. */
+	u_int8_t idk_keyix;	/* key index */
+	u_int8_t idk_macaddr[IEEE80211_ADDR_LEN];
+};
+
+/*
+ * MLME state manipulation request.  IEEE80211_MLME_ASSOC
+ * only makes sense when operating as a station.  The other
+ * requests can be used when operating as a station or an
+ * ap (to effect a station).
+ */
+struct ieee80211req_mlme {
+	u_int8_t im_op;			/* operation to perform */
+#define	IEEE80211_MLME_ASSOC		1	/* associate station */
+#define	IEEE80211_MLME_DISASSOC		2	/* disassociate station */
+#define	IEEE80211_MLME_DEAUTH		3	/* deauthenticate station */
+#define	IEEE80211_MLME_AUTHORIZE	4	/* authorize station */
+#define	IEEE80211_MLME_UNAUTHORIZE	5	/* unauthorize station */
+#define IEEE80211_MLME_CLEAR_STATS	6	/* clear station statistic */
+	u_int8_t im_ssid_len;		/* length of optional ssid */
+	u_int16_t im_reason;		/* 802.11 reason code */
+	u_int8_t im_macaddr[IEEE80211_ADDR_LEN];
+	u_int8_t im_ssid[IEEE80211_NWID_LEN];
+};
+
+/* 
+ * MAC ACL operations.
+ */
+enum {
+	IEEE80211_MACCMD_POLICY_OPEN	= 0,	/* set policy: no ACLs */
+	IEEE80211_MACCMD_POLICY_ALLOW	= 1,	/* set policy: allow traffic */
+	IEEE80211_MACCMD_POLICY_DENY	= 2,	/* set policy: deny traffic */
+	IEEE80211_MACCMD_FLUSH		= 3,	/* flush ACL database */
+	IEEE80211_MACCMD_DETACH		= 4,	/* detach ACL policy */
+};
+
+/*
+ * Set the active channel list.  Note this list is
+ * intersected with the available channel list in
+ * calculating the set of channels actually used in
+ * scanning.
+ */
+struct ieee80211req_chanlist {
+	u_int8_t ic_channels[IEEE80211_CHAN_BYTES];
+};
+
+/*
+ * Get the active channel list info.
+ */
+struct ieee80211req_chaninfo {
+	u_int ic_nchans;
+	struct ieee80211_channel ic_chans[IEEE80211_CHAN_MAX];
+};
+
+/*
+ * Retrieve the WPA/RSN information element for an associated station.
+ */
+struct ieee80211req_wpaie {
+	u_int8_t	wpa_macaddr[IEEE80211_ADDR_LEN];
+	u_int8_t	wpa_ie[IEEE80211_MAX_OPT_IE];
+	u_int8_t	rsn_ie[IEEE80211_MAX_OPT_IE];
+};
+
+/*
+ * Retrieve per-node statistics.
+ */
+struct ieee80211req_sta_stats {
+	union {
+		/* NB: explicitly force 64-bit alignment */
+		u_int8_t macaddr[IEEE80211_ADDR_LEN];
+		u_int64_t pad;
+	} is_u;
+	struct ieee80211_nodestats is_stats;
+};
+
+/*
+ * Station information block; the mac address is used
+ * to retrieve other data like stats, unicast key, etc.
+ */
+struct ieee80211req_sta_info {
+	u_int16_t isi_len;		/* length (mult of 4) */
+	u_int16_t isi_freq;		/* MHz */
+	u_int16_t isi_flags;		/* channel flags */
+	u_int16_t isi_state;		/* state flags */
+	u_int8_t isi_authmode;		/* authentication algorithm */
+	u_int8_t isi_rssi;
+	int8_t isi_noise;
+	u_int16_t isi_capinfo;		/* capabilities */
+	u_int8_t isi_athflags;		/* Atheros capabilities */
+	u_int8_t isi_erp;		/* ERP element */
+	u_int8_t isi_macaddr[IEEE80211_ADDR_LEN];
+	u_int8_t isi_nrates;		/* negotiated rates */
+	u_int8_t isi_rates[IEEE80211_RATE_MAXSIZE];
+	u_int8_t isi_txrate;		/* index to isi_rates[] */
+	u_int16_t isi_ie_len;		/* IE length */
+	u_int16_t isi_associd;		/* assoc response */
+	u_int16_t isi_txpower;		/* current tx power */
+	u_int16_t isi_vlan;		/* vlan tag */
+	u_int16_t isi_txseqs[17];	/* seq to be transmitted */
+	u_int16_t isi_rxseqs[17];	/* seq previous for qos frames*/
+	u_int16_t isi_inact;		/* inactivity timer */
+	u_int8_t isi_uapsd;		/* UAPSD queues */
+	u_int8_t isi_opmode;		/* sta operating mode */
+
+	/* XXX frag state? */
+	/* variable length IE data */
+};
+
+enum {
+	IEEE80211_STA_OPMODE_NORMAL,
+	IEEE80211_STA_OPMODE_XR
+};
+
+/*
+ * Retrieve per-station information; to retrieve all
+ * specify a mac address of ff:ff:ff:ff:ff:ff.
+ */
+struct ieee80211req_sta_req {
+	union {
+		/* NB: explicitly force 64-bit alignment */
+		u_int8_t macaddr[IEEE80211_ADDR_LEN];
+		u_int64_t pad;
+	} is_u;
+	struct ieee80211req_sta_info info[1];	/* variable length */
+};
+
+/*
+ * Get/set per-station tx power cap.
+ */
+struct ieee80211req_sta_txpow {
+	u_int8_t	it_macaddr[IEEE80211_ADDR_LEN];
+	u_int8_t	it_txpow;
+};
+
+/*
+ * WME parameters are set and return using i_val and i_len.
+ * i_val holds the value itself.  i_len specifies the AC
+ * and, as appropriate, then high bit specifies whether the
+ * operation is to be applied to the BSS or ourself.
+ */
+#define	IEEE80211_WMEPARAM_SELF	0x0000		/* parameter applies to self */
+#define	IEEE80211_WMEPARAM_BSS	0x8000		/* parameter applies to BSS */
+#define	IEEE80211_WMEPARAM_VAL	0x7fff		/* parameter value */
+
+/*
+ * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
+ */
+struct ieee80211req_scan_result {
+	u_int16_t isr_len;		/* length (mult of 4) */
+	u_int16_t isr_freq;		/* MHz */
+	u_int16_t isr_flags;		/* channel flags */
+	u_int8_t isr_noise;
+	u_int8_t isr_rssi;
+	u_int8_t isr_intval;		/* beacon interval */
+	u_int16_t isr_capinfo;		/* capabilities */
+	u_int8_t isr_erp;		/* ERP element */
+	u_int8_t isr_bssid[IEEE80211_ADDR_LEN];
+	u_int8_t isr_nrates;
+	u_int8_t isr_rates[IEEE80211_RATE_MAXSIZE];
+	u_int8_t isr_ssid_len;		/* SSID length */
+	u_int8_t isr_ie_len;		/* IE length */
+	u_int8_t isr_pad[5];
+	/* variable length SSID followed by IE data */
+};
+
+#ifdef __FreeBSD__
+/*
+ * FreeBSD-style ioctls.
+ */
+/* the first member must be matched with struct ifreq */
+struct ieee80211req {
+	char i_name[IFNAMSIZ];	/* if_name, e.g. "wi0" */
+	u_int16_t i_type;	/* req type */
+	int16_t 	i_val;		/* Index or simple value */
+	int16_t 	i_len;		/* Index or simple value */
+	void *i_data;		/* Extra data */
+};
+#define	SIOCS80211		 _IOW('i', 234, struct ieee80211req)
+#define	SIOCG80211		_IOWR('i', 235, struct ieee80211req)
+#define	SIOCG80211STATS		_IOWR('i', 236, struct ifreq)
+#define	SIOC80211IFCREATE	_IOWR('i', 237, struct ifreq)
+#define	SIOC80211IFDESTROY	 _IOW('i', 238, struct ifreq)
+
+#define IEEE80211_IOC_SSID		1
+#define IEEE80211_IOC_NUMSSIDS		2
+#define IEEE80211_IOC_WEP		3
+#define 	IEEE80211_WEP_NOSUP		-1
+#define 	IEEE80211_WEP_OFF		0
+#define 	IEEE80211_WEP_ON		1
+#define 	IEEE80211_WEP_MIXED		2
+#define IEEE80211_IOC_WEPKEY		4
+#define IEEE80211_IOC_NUMWEPKEYS	5
+#define IEEE80211_IOC_WEPTXKEY		6
+#define IEEE80211_IOC_AUTHMODE		7
+#define IEEE80211_IOC_STATIONNAME	8
+#define IEEE80211_IOC_CHANNEL		9
+#define IEEE80211_IOC_POWERSAVE		10
+#define 	IEEE80211_POWERSAVE_NOSUP	-1
+#define 	IEEE80211_POWERSAVE_OFF		0
+#define 	IEEE80211_POWERSAVE_CAM		1
+#define 	IEEE80211_POWERSAVE_PSP		2
+#define 	IEEE80211_POWERSAVE_PSP_CAM	3
+#define 	IEEE80211_POWERSAVE_ON		IEEE80211_POWERSAVE_CAM
+#define IEEE80211_IOC_POWERSAVESLEEP	11
+#define	IEEE80211_IOC_RTSTHRESHOLD	12
+#define IEEE80211_IOC_PROTMODE		13
+#define 	IEEE80211_PROTMODE_OFF		0
+#define 	IEEE80211_PROTMODE_CTS		1
+#define 	IEEE80211_PROTMODE_RTSCTS	2
+#define	IEEE80211_IOC_TXPOWER		14	/* global tx power limit */
+#define	IEEE80211_IOC_BSSID		15
+#define	IEEE80211_IOC_ROAMING		16	/* roaming mode */
+#define	IEEE80211_IOC_PRIVACY		17	/* privacy invoked */
+#define	IEEE80211_IOC_DROPUNENCRYPTED	18	/* discard unencrypted frames */
+#define	IEEE80211_IOC_WPAKEY		19
+#define	IEEE80211_IOC_DELKEY		20
+#define	IEEE80211_IOC_MLME		21
+#define	IEEE80211_IOC_OPTIE		22	/* optional info. element */
+#define	IEEE80211_IOC_SCAN_REQ		23
+#define	IEEE80211_IOC_SCAN_RESULTS	24
+#define	IEEE80211_IOC_COUNTERMEASURES	25	/* WPA/TKIP countermeasures */
+#define	IEEE80211_IOC_WPA		26	/* WPA mode (0,1,2) */
+#define	IEEE80211_IOC_CHANLIST		27	/* channel list */
+#define	IEEE80211_IOC_WME		28	/* WME mode (on, off) */
+#define	IEEE80211_IOC_HIDESSID		29	/* hide SSID mode (on, off) */
+#define IEEE80211_IOC_APBRIDGE		30	/* AP inter-sta bridging */
+#define	IEEE80211_IOC_MCASTCIPHER	31	/* multicast/default cipher */
+#define	IEEE80211_IOC_MCASTKEYLEN	32	/* multicast key length */
+#define	IEEE80211_IOC_UCASTCIPHERS	33	/* unicast cipher suites */
+#define	IEEE80211_IOC_UCASTCIPHER	34	/* unicast cipher */
+#define	IEEE80211_IOC_UCASTKEYLEN	35	/* unicast key length */
+#define	IEEE80211_IOC_DRIVER_CAPS	36	/* driver capabilities */
+#define	IEEE80211_IOC_KEYMGTALGS	37	/* key management algorithms */
+#define	IEEE80211_IOC_RSNCAPS		38	/* RSN capabilities */
+#define	IEEE80211_IOC_WPAIE		39	/* WPA information element */
+#define	IEEE80211_IOC_STA_STATS		40	/* per-station statistics */
+#define	IEEE80211_IOC_MACCMD		41	/* MAC ACL operation */
+#define	IEEE80211_IOC_TXPOWMAX		43	/* max tx power for channel */
+#define	IEEE80211_IOC_STA_TXPOW		44	/* per-station tx power limit */
+#define	IEEE80211_IOC_STA_INFO		45	/* station/neighbor info */
+#define	IEEE80211_IOC_WME_CWMIN		46	/* WME: ECWmin */
+#define	IEEE80211_IOC_WME_CWMAX		47	/* WME: ECWmax */
+#define	IEEE80211_IOC_WME_AIFS		48	/* WME: AIFSN */
+#define	IEEE80211_IOC_WME_TXOPLIMIT	49	/* WME: txops limit */
+#define	IEEE80211_IOC_WME_ACM		50	/* WME: ACM (bss only) */
+#define	IEEE80211_IOC_WME_ACKPOLICY	51	/* WME: ACK policy (!bss only)*/
+#define	IEEE80211_IOC_DTIM_PERIOD	52	/* DTIM period (beacons) */
+#define	IEEE80211_IOC_BEACON_INTERVAL	53	/* beacon interval (ms) */
+#define	IEEE80211_IOC_ADDMAC		54	/* add sta to MAC ACL table */
+#define	IEEE80211_IOC_DELMAC		55	/* del sta from MAC ACL table */
+#define	IEEE80211_IOC_FF		56	/* ATH fast frames (on, off) */
+#define	IEEE80211_IOC_TURBOP		57	/* ATH turbo' (on, off) */
+#define	IEEE80211_IOC_APPIEBUF		58	/* IE in the management frame */
+#define	IEEE80211_IOC_FILTERFRAME	59	/* management frame filter */
+
+/*
+ * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
+ */
+struct ieee80211req_scan_result {
+	u_int16_t isr_len;		/* length (mult of 4) */
+	u_int16_t isr_freq;		/* MHz */
+	u_int16_t isr_flags;		/* channel flags */
+	u_int8_t isr_noise;
+	u_int8_t isr_rssi;
+	u_int8_t isr_intval;		/* beacon interval */
+	u_int16_t isr_capinfo;		/* capabilities */
+	u_int8_t isr_erp;		/* ERP element */
+	u_int8_t isr_bssid[IEEE80211_ADDR_LEN];
+	u_int8_t isr_nrates;
+	u_int8_t isr_rates[IEEE80211_RATE_MAXSIZE];
+	u_int8_t isr_ssid_len;		/* SSID length */
+	u_int8_t isr_ie_len;		/* IE length */
+	u_int8_t isr_pad[5];
+	/* variable length SSID followed by IE data */
+};
+
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+/*
+ * Wireless Extensions API, private ioctl interfaces.
+ *
+ * NB: Even-numbered ioctl numbers have set semantics and are privileged!
+ *     (regardless of the incorrect comment in wireless.h!)
+ */
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+/* The maximum size of a iwpriv structure is IW_PRIV_SIZE_MASK, which was 
+ * exceeded for some time by chaninfo ioctl.  These macros change the size 
+ * encoding for anything larger than IW_PRIV_SIZE_MASK from bytes to 4-byte
+ * multiples so that the padded size fits under IW_PRIV_SIZE_MASK. */
+#define IW_PRIV_BLOB_LENGTH_ENCODING(_SIZE) \
+	(((_SIZE) == ((_SIZE) & IW_PRIV_SIZE_MASK)) ? \
+		(_SIZE) : \
+		(((_SIZE) / sizeof(uint32_t)) + \
+			(((_SIZE) == (((_SIZE) / sizeof(uint32_t)) * sizeof(int))) ? \
+				0 : 1)))
+#define IW_PRIV_BLOB_TYPE_ENCODING(_SIZE) \
+	(((_SIZE) == ((_SIZE) & IW_PRIV_SIZE_MASK)) ? \
+		(IW_PRIV_TYPE_BYTE | (_SIZE)) : \
+		(IW_PRIV_TYPE_INT  | IW_PRIV_BLOB_LENGTH_ENCODING((_SIZE))))
+
+#define	IEEE80211_IOCTL_SETPARAM	(SIOCIWFIRSTPRIV+0)
+#define	IEEE80211_IOCTL_GETPARAM	(SIOCIWFIRSTPRIV+1)
+#define	IEEE80211_IOCTL_SETMODE		(SIOCIWFIRSTPRIV+2)
+#define	IEEE80211_IOCTL_GETMODE		(SIOCIWFIRSTPRIV+3)
+#define	IEEE80211_IOCTL_SETWMMPARAMS	(SIOCIWFIRSTPRIV+4)
+#define	IEEE80211_IOCTL_GETWMMPARAMS	(SIOCIWFIRSTPRIV+5)
+#define	IEEE80211_IOCTL_SETCHANLIST	(SIOCIWFIRSTPRIV+6)
+#define	IEEE80211_IOCTL_GETCHANLIST	(SIOCIWFIRSTPRIV+7)
+#define	IEEE80211_IOCTL_CHANSWITCH	(SIOCIWFIRSTPRIV+8)
+#define	IEEE80211_IOCTL_GET_APPIEBUF	(SIOCIWFIRSTPRIV+9)
+#define	IEEE80211_IOCTL_SET_APPIEBUF	(SIOCIWFIRSTPRIV+10)
+#define	IEEE80211_IOCTL_READREG		(SIOCIWFIRSTPRIV+11)
+#define	IEEE80211_IOCTL_FILTERFRAME	(SIOCIWFIRSTPRIV+12)
+#define	IEEE80211_IOCTL_GETCHANINFO	(SIOCIWFIRSTPRIV+13)
+#define	IEEE80211_IOCTL_SETOPTIE	(SIOCIWFIRSTPRIV+14)
+#define	IEEE80211_IOCTL_GETOPTIE	(SIOCIWFIRSTPRIV+15)
+#define	IEEE80211_IOCTL_SETMLME		(SIOCIWFIRSTPRIV+16)
+#define	IEEE80211_IOCTL_RADAR		(SIOCIWFIRSTPRIV+17)
+#define	IEEE80211_IOCTL_SETKEY		(SIOCIWFIRSTPRIV+18)
+#define	IEEE80211_IOCTL_WRITEREG	(SIOCIWFIRSTPRIV+19)
+#define	IEEE80211_IOCTL_DELKEY		(SIOCIWFIRSTPRIV+20)
+#define	IEEE80211_IOCTL_HALMAP		(SIOCIWFIRSTPRIV+21)
+#define	IEEE80211_IOCTL_ADDMAC		(SIOCIWFIRSTPRIV+22)
+#define	IEEE80211_IOCTL_DELMAC		(SIOCIWFIRSTPRIV+24)
+#define	IEEE80211_IOCTL_WDSADDMAC	(SIOCIWFIRSTPRIV+26)
+#define	IEEE80211_IOCTL_WDSDELMAC	(SIOCIWFIRSTPRIV+28)
+#define	IEEE80211_IOCTL_KICKMAC		(SIOCIWFIRSTPRIV+30)
+#define	IEEE80211_IOCTL_SETSCANLIST	(SIOCIWFIRSTPRIV+31)
+
+enum {
+	IEEE80211_WMMPARAMS_CWMIN       = 1,
+	IEEE80211_WMMPARAMS_CWMAX       = 2,
+	IEEE80211_WMMPARAMS_AIFS       	= 3,
+	IEEE80211_WMMPARAMS_TXOPLIMIT	= 4,
+	IEEE80211_WMMPARAMS_ACM		= 5,
+	IEEE80211_WMMPARAMS_NOACKPOLICY	= 6,
+};
+enum {
+	IEEE80211_PARAM_TURBO			= 1,	/* turbo mode */
+	IEEE80211_PARAM_MODE			= 2,	/* phy mode (11a, 11b, etc.) */
+	IEEE80211_PARAM_AUTHMODE		= 3,	/* authentication mode */
+	IEEE80211_PARAM_PROTMODE		= 4,	/* 802.11g protection */
+	IEEE80211_PARAM_MCASTCIPHER		= 5,	/* multicast/default cipher */
+	IEEE80211_PARAM_MCASTKEYLEN		= 6,	/* multicast key length */
+	IEEE80211_PARAM_UCASTCIPHERS		= 7,	/* unicast cipher suites */
+	IEEE80211_PARAM_UCASTCIPHER		= 8,	/* unicast cipher */
+	IEEE80211_PARAM_UCASTKEYLEN		= 9,	/* unicast key length */
+	IEEE80211_PARAM_WPA			= 10,	/* WPA mode (0,1,2) */
+	IEEE80211_PARAM_ROAMING			= 12,	/* roaming mode */
+	IEEE80211_PARAM_PRIVACY			= 13,	/* privacy invoked */
+	IEEE80211_PARAM_COUNTERMEASURES		= 14,	/* WPA/TKIP countermeasures */
+	IEEE80211_PARAM_DROPUNENCRYPTED		= 15,	/* discard unencrypted frames */
+	IEEE80211_PARAM_DRIVER_CAPS		= 16,	/* driver capabilities */
+	IEEE80211_PARAM_MACCMD			= 17,	/* MAC ACL operation */
+	IEEE80211_PARAM_WMM			= 18,	/* WMM mode (on, off) */
+	IEEE80211_PARAM_HIDESSID		= 19,	/* hide SSID mode (on, off) */
+	IEEE80211_PARAM_APBRIDGE    		= 20,   /* AP inter-sta bridging */
+	IEEE80211_PARAM_KEYMGTALGS		= 21,	/* key management algorithms */
+	IEEE80211_PARAM_RSNCAPS			= 22,	/* RSN capabilities */
+	IEEE80211_PARAM_INACT			= 23,	/* station inactivity timeout */
+	IEEE80211_PARAM_INACT_AUTH		= 24,	/* station auth inact timeout */
+	IEEE80211_PARAM_INACT_INIT		= 25,	/* station init inact timeout */
+	IEEE80211_PARAM_ABOLT			= 26,	/* Atheros Adv. Capabilities */
+	IEEE80211_PARAM_DTIM_PERIOD		= 28,	/* DTIM period (beacons) */
+	IEEE80211_PARAM_BEACON_INTERVAL		= 29,	/* beacon interval (ms) */
+	IEEE80211_PARAM_DOTH			= 30,	/* 11.h is on/off */
+	IEEE80211_PARAM_PWRTARGET		= 31,	/* Current Channel Pwr Constraint */
+	IEEE80211_PARAM_GENREASSOC		= 32,	/* Generate a reassociation request */
+	IEEE80211_PARAM_COMPRESSION		= 33,	/* compression */
+	IEEE80211_PARAM_FF			= 34,	/* fast frames support  */
+	IEEE80211_PARAM_XR			= 35,	/* XR support */
+	IEEE80211_PARAM_BURST			= 36,	/* burst mode */
+	IEEE80211_PARAM_PUREG			= 37,	/* pure 11g (no 11b stations) */
+	IEEE80211_PARAM_AR			= 38,	/* AR support */
+	IEEE80211_PARAM_WDS			= 39,	/* Enable 4 address processing */
+	IEEE80211_PARAM_BGSCAN			= 40,	/* bg scanning (on, off) */
+	IEEE80211_PARAM_BGSCAN_IDLE		= 41,	/* bg scan idle threshold */
+	IEEE80211_PARAM_BGSCAN_INTERVAL		= 42,	/* bg scan interval */
+	IEEE80211_PARAM_MCAST_RATE		= 43,	/* Multicast Tx Rate */
+	IEEE80211_PARAM_COVERAGE_CLASS		= 44,	/* coverage class */
+	IEEE80211_PARAM_COUNTRY_IE		= 45,	/* enable country IE */
+	IEEE80211_PARAM_SCANVALID		= 46,	/* scan cache valid threshold */
+	IEEE80211_PARAM_ROAM_RSSI_11A		= 47,	/* rssi threshold in 11a */
+	IEEE80211_PARAM_ROAM_RSSI_11B		= 48,	/* rssi threshold in 11b */
+	IEEE80211_PARAM_ROAM_RSSI_11G		= 49,	/* rssi threshold in 11g */
+	IEEE80211_PARAM_ROAM_RATE_11A		= 50,	/* tx rate threshold in 11a */
+	IEEE80211_PARAM_ROAM_RATE_11B		= 51,	/* tx rate threshold in 11b */
+	IEEE80211_PARAM_ROAM_RATE_11G		= 52,	/* tx rate threshold in 11g */
+	IEEE80211_PARAM_UAPSDINFO		= 53,	/* value for qos info field */
+	IEEE80211_PARAM_SLEEP			= 54,	/* force sleep/wake */
+	IEEE80211_PARAM_QOSNULL			= 55,	/* force sleep/wake */
+	IEEE80211_PARAM_PSPOLL			= 56,	/* force ps-poll generation (sta only) */
+	IEEE80211_PARAM_EOSPDROP		= 57,	/* force uapsd EOSP drop (ap only) */
+	IEEE80211_PARAM_MARKDFS			= 58,	/* mark a dfs interference channel when found */
+	IEEE80211_PARAM_REGCLASS		= 59,	/* enable regclass ids in country IE */
+	IEEE80211_PARAM_DROPUNENC_EAPOL		= 60,	/* drop unencrypted eapol frames */
+	IEEE80211_PARAM_SHPREAMBLE		= 61,	/* Short Preamble */
+	IEEE80211_PARAM_DUMPREGS		= 62,	/* Pretty printed dump of Atheros hardware registers */
+	IEEE80211_PARAM_DOTH_ALGORITHM		= 63,	/* spectrum management algorithm */
+	IEEE80211_PARAM_DOTH_MINCOM   		= 64,	/* minimum number of common channels */
+	IEEE80211_PARAM_DOTH_SLCG		= 65,	/* permil of Stations Lost per Channel Gained */
+	IEEE80211_PARAM_DOTH_SLDG		= 66,	/* permil of Stations Lost per rssi Db Gained */
+	IEEE80211_PARAM_TXCONT			= 67,	/* continuous transmit mode (boolean) */
+	IEEE80211_PARAM_TXCONT_RATE		= 68,	/* continuous transmit mode data rate (in mbit/sec) - will use closest match from current rate table */
+	IEEE80211_PARAM_TXCONT_POWER		= 69,	/* power level in units of 0.5dBm */
+	IEEE80211_PARAM_DFS_TESTMODE		= 70,	/* do not perform DFS actions (i.e. markng DFS and channel change on interference), just report them via debug. */
+	IEEE80211_PARAM_DFS_CACTIME		= 71,	/* how long do we wait for chan availability
+							   scans ?
+							   FCC requires 60s, so that is the default. */
+	IEEE80211_PARAM_DFS_EXCLPERIOD		= 72,	/* DFS no-occupancy limit - how long do we stay
+							   off a channel once radar is detected?
+							   FCC requires 30m, so that is the default. */
+	IEEE80211_PARAM_BEACON_MISS_THRESH	= 73,	/* Beacon miss threshold (in beacons) */
+	IEEE80211_PARAM_BEACON_MISS_THRESH_MS	= 74,	/* Beacon miss threshold (in ms) */
+	IEEE80211_PARAM_MAXRATE			= 75,	/* Maximum rate (by table index) */
+	IEEE80211_PARAM_MINRATE			= 76,	/* Maximum rate (by table index) */
+	IEEE80211_PARAM_PROTMODE_RSSI		= 77,	/* RSSI Threshold for enabling protection mode */
+	IEEE80211_PARAM_PROTMODE_TIMEOUT	= 78,	/* Timeout for expiring protection mode */
+};
+
+#define	SIOCG80211STATS			(SIOCDEVPRIVATE+2)
+/* NB: require in+out parameters so cannot use wireless extensions, yech */
+#define	IEEE80211_IOCTL_GETKEY		(SIOCDEVPRIVATE+3)
+#define	IEEE80211_IOCTL_GETWPAIE	(SIOCDEVPRIVATE+4)
+#define	IEEE80211_IOCTL_STA_STATS	(SIOCDEVPRIVATE+5)
+#define	IEEE80211_IOCTL_STA_INFO	(SIOCDEVPRIVATE+6)
+#define	SIOC80211IFCREATE		(SIOCDEVPRIVATE+7)
+#define	SIOC80211IFDESTROY	 	(SIOCDEVPRIVATE+8)
+#define	IEEE80211_IOCTL_SCAN_RESULTS	(SIOCDEVPRIVATE+9)
+
+struct ieee80211_clone_params {
+	char icp_name[IFNAMSIZ];		/* device name */
+	u_int16_t icp_opmode;			/* operating mode */
+	u_int16_t icp_flags;			/* see below */
+#define	IEEE80211_CLONE_BSSID	0x0001		/* allocate unique mac/bssid */
+#define	IEEE80211_NO_STABEACONS	0x0002		/* Do not setup the station beacon timers */
+};
+
+/* APPIEBUF related definitions */
+
+/* Management frame type to which application IE is added */
+enum {
+	IEEE80211_APPIE_FRAME_BEACON		= 0,
+	IEEE80211_APPIE_FRAME_PROBE_REQ		= 1,
+	IEEE80211_APPIE_FRAME_PROBE_RESP	= 2,
+	IEEE80211_APPIE_FRAME_ASSOC_REQ		= 3,
+	IEEE80211_APPIE_FRAME_ASSOC_RESP	= 4,
+	IEEE80211_APPIE_NUM_OF_FRAME		= 5
+};
+
+struct ieee80211req_getset_appiebuf {
+	u_int32_t	app_frmtype;		/* management frame type for which buffer is added */
+	u_int32_t	app_buflen;		/* application-supplied buffer length */
+	u_int8_t	app_buf[0];		/* application-supplied IE(s) */
+};
+
+/* Flags ORed by application to set filter for receiving management frames */
+enum {
+	IEEE80211_FILTER_TYPE_BEACON		= 1<<0,
+	IEEE80211_FILTER_TYPE_PROBE_REQ		= 1<<1,
+	IEEE80211_FILTER_TYPE_PROBE_RESP	= 1<<2,
+	IEEE80211_FILTER_TYPE_ASSOC_REQ		= 1<<3,
+	IEEE80211_FILTER_TYPE_ASSOC_RESP	= 1<<4,
+	IEEE80211_FILTER_TYPE_AUTH		= 1<<5,
+	IEEE80211_FILTER_TYPE_DEAUTH		= 1<<6,
+	IEEE80211_FILTER_TYPE_DISASSOC		= 1<<7,
+	IEEE80211_FILTER_TYPE_ALL		= 0xFF	/* used to check the valid filter bits */
+};
+
+struct ieee80211req_set_filter {
+	u_int32_t app_filterype;		/* management frame filter type */
+};
+
+
+#endif /* __linux__ */
+
+#endif /* _NET80211_IEEE80211_IOCTL_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_linux.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_linux.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_linux.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_linux.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,647 @@
+/*-
+ * Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_linux.h 3269 2008-01-26 20:56:20Z mtaylor $
+ */
+#ifndef _NET80211_IEEE80211_LINUX_H_
+#define _NET80211_IEEE80211_LINUX_H_
+
+/* #define ATH_DEBUG_SPINLOCKS */		/* announce before spinlocking */
+
+#include <linux/wireless.h>
+#include <linux/fs.h>
+
+/*
+ * Compatibility definition of statistics flags
+ * (bitmask in (struct iw_quality *)->updated)
+ */
+#ifndef IW_QUAL_QUAL_UPDATED
+#define IW_QUAL_QUAL_UPDATED	0x01	/* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED	0x02
+#define IW_QUAL_NOISE_UPDATED	0x04
+#define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID	0x20
+#define IW_QUAL_NOISE_INVALID	0x40
+#endif /* IW_QUAL_QUAL_UPDATED */
+
+#ifndef IW_QUAL_ALL_UPDATED
+#define IW_QUAL_ALL_UPDATED \
+	(IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED)
+#endif
+#ifndef IW_QUAL_ALL_INVALID
+#define IW_QUAL_ALL_INVALID \
+	(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID)
+#endif
+
+/*
+ * The RSSI values reported in the TX/RX descriptors in the driver are the SNR 
+ * expressed in dBm. Thus 'rssi' is signal level above the noise floor in dBm.
+ *
+ * Noise is measured in dBm and is negative unless there is an unimaginable 
+ * level of RF noise. 
+ *
+ * The signal level is noise + rssi.
+ *
+ * Note that the iw_quality values are 1 byte, and can be signed, unsigned or 
+ * negative depending on context.
+ *
+ */
+static __inline void
+set_quality(struct iw_quality *iq, u_int rssi, int noise)
+{
+	iq->qual = rssi;
+	iq->noise = noise;
+	iq->level = ((((int)rssi + noise) <= 0) ? ((int)rssi + noise) : 0);
+	iq->updated = IW_QUAL_ALL_UPDATED;
+#if WIRELESS_EXT >= 19
+	iq->updated |= IW_QUAL_DBM;
+#endif
+}
+
+/*
+ * Task deferral
+ *
+ * Deduce if tasklets are available.  If not then
+ * fall back to using the immediate work queue.
+ */
+#include <linux/interrupt.h>
+#ifdef DECLARE_TASKLET			/* native tasklets */
+#define IEEE80211_TQ_STRUCT tasklet_struct
+#define IEEE80211_INIT_TQUEUE(a,b,c)	tasklet_init((a), (b), (unsigned long)(c))
+#define IEEE80211_SCHEDULE_TQUEUE(a)	tasklet_schedule((a))
+#define IEEE80211_CANCEL_TQUEUE(a)	if (!in_interrupt()) tasklet_kill((a))
+typedef unsigned long IEEE80211_TQUEUE_ARG;
+#define mark_bh(a) do {} while (0)
+#else					/* immediate work queue */
+#define IEEE80211_TQ_STRUCT tq_struct
+#define IEEE80211_INIT_TQUEUE(a,b,c)		INIT_TQUEUE(a,b,c)
+#define IEEE80211_SCHEDULE_TQUEUE(a) do { \
+	int __macro_needmark;		\
+	__macro_needmark |= queue_task((a), &tq_immediate);	\
+	if (__macro_needmark)		\
+		mark_bh(IMMEDIATE_BH);	\
+} while (0)
+typedef void *IEEE80211_TQUEUE_ARG;
+#define	tasklet_disable(t)	do { (void) t; local_bh_disable(); } while (0)
+#define	tasklet_enable(t)	do { (void) t; local_bh_enable(); } while (0)
+/* XXX: not supporting cancel in old kernels! */
+#define IEEE80211_CANCEL_TQUEUE(a)	((a), 0)
+#endif /* !DECLARE_TASKLET */
+
+#define	IEEE80211_RESCHEDULE	schedule
+
+/* Locking */
+/* NB: beware, spin_is_locked() is not usefully defined for !(DEBUG || SMP)
+ * because spinlocks do not exist in this configuration. Instead IRQs 
+ * or pre-emption are simply disabled, as this is all that is needed.
+ */
+
+/*
+ * Beacon handler locking definitions.
+ * Beacon locking 
+ * UAPSD locking 
+ */
+typedef spinlock_t ieee80211com_lock_t;
+#define	IEEE80211_LOCK_INIT(_ic, _name)					\
+	spin_lock_init(&(_ic)->ic_comlock)
+#define	IEEE80211_LOCK_DESTROY(_ic)
+#define	IEEE80211_LOCK_IRQ(_ic) do {					\
+	unsigned long __ilockflags;					\
+	IEEE80211_LOCK_CHECK(_ic);					\
+	spin_lock_irqsave(&(_ic)->ic_comlock, __ilockflags);
+#define	IEEE80211_UNLOCK_IRQ(_ic)					\
+	IEEE80211_LOCK_ASSERT(_ic);					\
+	spin_unlock_irqrestore(&(_ic)->ic_comlock, __ilockflags);	\
+} while (0)
+#define	IEEE80211_UNLOCK_IRQ_EARLY(_ic)					\
+	IEEE80211_LOCK_ASSERT(_ic);					\
+	spin_unlock_irqrestore(&(_ic)->ic_comlock, __ilockflags);
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define	IEEE80211_LOCK_ASSERT(_ic) \
+	KASSERT(spin_is_locked(&(_ic)->ic_comlock), ("ieee80211com not locked!"))
+#if (defined(ATH_DEBUG_SPINLOCKS))
+#define	IEEE80211_LOCK_CHECK(_ic) do { \
+	if (spin_is_locked(&(_ic)->ic_comlock)) \
+		printk("%s:%d - about to block on ieee80211com lock!\n", __func__, __LINE__); \
+} while(0)
+#else /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#define	IEEE80211_LOCK_CHECK(_ic)
+#endif 
+#else
+#define	IEEE80211_LOCK_ASSERT(_ic)
+#define	IEEE80211_LOCK_CHECK(_ic)
+#endif
+
+
+#define IEEE80211_VAPS_LOCK_INIT(_ic, _name)		\
+	spin_lock_init(&(_ic)->ic_vapslock)
+#define IEEE80211_VAPS_LOCK_DESTROY(_ic)
+#define IEEE80211_VAPS_LOCK_BH(_ic)	do { 		\
+	IEEE80211_VAPS_LOCK_CHECK(_ic);		\
+	spin_lock_bh(&(_ic)->ic_vapslock);
+#define IEEE80211_VAPS_UNLOCK_BH(_ic)			\
+	IEEE80211_VAPS_LOCK_ASSERT(_ic);		\
+	spin_unlock_bh(&(_ic)->ic_vapslock);		\
+} while (0)
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define IEEE80211_VAPS_LOCK_ASSERT(_ic) \
+	KASSERT(spin_is_locked(&(_ic)->ic_vapslock), \
+		("ieee80211com_vaps not locked!"))
+#if (defined(ATH_DEBUG_SPINLOCKS))
+#define	IEEE80211_VAPS_LOCK_CHECK(_ic) do { \
+	if (spin_is_locked(&(_ic)->ic_vapslock)) \
+		printk("%s:%d - about to block on ieee80211com_vaps lock!\n", __func__, __LINE__); \
+} while(0)
+#else /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#define IEEE80211_VAPS_LOCK_CHECK(_ic)
+#endif /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#else
+#define IEEE80211_VAPS_LOCK_ASSERT(_ic)
+#define IEEE80211_VAPS_LOCK_CHECK(_ic)
+#endif
+
+
+/*
+ * Node locking definitions.
+ */
+#if 0
+
+typedef spinlock_t ieee80211_node_lock_t;
+#define	IEEE80211_NODE_LOCK_INIT(_ni, _name)	spin_lock_init(&(_ni)->ni_nodelock)
+#define	IEEE80211_NODE_LOCK_DESTROY(_ni)
+#define	IEEE80211_NODE_LOCK_IRQ(_ni)	do {	\
+	unsigned long __node_lockflags;		\
+	IEEE80211_NODE_LOCK_CHECK(_ni); 	\
+	spin_lock_irqsave(&(_ni)->ni_nodelock, __node_lockflags);
+#define	IEEE80211_NODE_UNLOCK_IRQ(_ni) \
+	IEEE80211_NODE_LOCK_ASSERT(_ni); \
+	spin_unlock_irqrestore(&(_ni)->ni_nodelock, __node_lockflags); \
+} while (0)
+#define	IEEE80211_NODE_UNLOCK_IRQ_EARLY(_ni)		\
+	IEEE80211_NODE_LOCK_ASSERT(_ni); \
+	spin_unlock_irqrestore(&(_ni)->ni_nodelock, __node_lockflags);
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define	IEEE80211_NODE_LOCK_ASSERT(_ni) \
+	KASSERT(spin_is_locked(&(_ni)->ni_nodelock), \
+		("802.11 node not locked!"))
+#if (defined(ATH_DEBUG_SPINLOCKS))
+#define	IEEE80211_NODE_LOCK_CHECK(_ni) do { \
+	if (spin_is_locked(&(_ni)->ni_nodelock)) \
+		printk("%s:%d - about to block on node lock!\n", __func__, __LINE__); \
+} while(0)
+#else /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#define	IEEE80211_NODE_LOCK_CHECK(_ni)
+#endif /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#else
+#define	IEEE80211_NODE_LOCK_ASSERT(_ni)
+#define	IEEE80211_NODE_LOCK_CHECK(_ni)
+#endif
+
+#endif /* node lock */
+
+/*
+ * Node table locking definitions.
+ */
+typedef spinlock_t ieee80211_node_table_lock_t;
+#define	IEEE80211_NODE_TABLE_LOCK_INIT(_nt, _name)	spin_lock_init(&(_nt)->nt_nodelock)
+#define	IEEE80211_NODE_TABLE_LOCK_DESTROY(_nt)
+#if 0	/* We should always be contesting in the same contexts */
+#define	IEEE80211_NODE_TABLE_LOCK(_nt)	spin_lock(&(_nt)->nt_nodelock)
+#define	IEEE80211_NODE_TABLE_UNLOCK(_nt)	spin_unlock(&(_nt)->nt_nodelock)
+#define	IEEE80211_NODE_TABLE_LOCK_BH(_nt)	spin_lock_bh(&(_nt)->nt_nodelock)
+#define	IEEE80211_NODE_TABLE_UNLOCK_BH(_nt)	spin_unlock_bh(&(_nt)->nt_nodelock)
+#endif
+#define	IEEE80211_NODE_TABLE_LOCK_IRQ(_nt)	do {	\
+	unsigned long __node_lockflags;		\
+	spin_lock_irqsave(&(_nt)->nt_nodelock, __node_lockflags);
+#define	IEEE80211_NODE_TABLE_UNLOCK_IRQ(_nt)		\
+	spin_unlock_irqrestore(&(_nt)->nt_nodelock, __node_lockflags); \
+} while (0)
+#define	IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(_nt)		\
+	spin_unlock_irqrestore(&(_nt)->nt_nodelock, __node_lockflags);
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define	IEEE80211_NODE_TABLE_LOCK_ASSERT(_nt) \
+	KASSERT(spin_is_locked(&(_nt)->nt_nodelock), \
+		("802.11 node table not locked!"))
+#else
+#define	IEEE80211_NODE_TABLE_LOCK_ASSERT(_nt)
+#endif
+
+/*
+ * Node table scangen locking definitions.
+ */
+typedef spinlock_t ieee80211_scan_lock_t;
+#define	IEEE80211_SCAN_LOCK_INIT(_nt, _name) spin_lock_init(&(_nt)->nt_scanlock)
+#define	IEEE80211_SCAN_LOCK_DESTROY(_nt)
+#define	IEEE80211_SCAN_LOCK_IRQ(_nt)	do {	\
+	unsigned long __scan_lockflags;		\
+	spin_lock_irqsave(&(_nt)->nt_scanlock, __scan_lockflags);
+#define	IEEE80211_SCAN_UNLOCK_IRQ(_nt)		\
+	spin_unlock_irqrestore(&(_nt)->nt_scanlock, __scan_lockflags); \
+} while (0)
+#define	IEEE80211_SCAN_UNLOCK_IRQ_EARLY(_nt)		\
+	spin_unlock_irqrestore(&(_nt)->nt_scanlock, __scan_lockflags);
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define	IEEE80211_SCAN_LOCK_ASSERT(_nt) \
+	KASSERT(spin_is_locked(&(_nt)->nt_scanlock), ("scangen not locked!"))
+#else
+#define	IEEE80211_SCAN_LOCK_ASSERT(_nt)
+#endif
+
+/*
+ * 802.1x MAC ACL database locking definitions.
+ */
+typedef spinlock_t acl_lock_t;
+#define	ACL_LOCK_INIT(_as, _name)	spin_lock_init(&(_as)->as_lock)
+#define	ACL_LOCK_DESTROY(_as)
+#define	ACL_LOCK(_as)			do { 	\
+	ACL_LOCK_CHECK(_as); 		\
+	spin_lock(&(_as)->as_lock);
+#define	ACL_UNLOCK(_as)				\
+	ACL_LOCK_ASSERT(_as); 			\
+	spin_unlock(&(_as)->as_lock); 		\
+} while(0)
+#define ACL_UNLOCK_EARLY(_as)			\
+	ACL_LOCK_ASSERT(_as); 			\
+	spin_unlock(&(_as)->as_lock);
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define	ACL_LOCK_ASSERT(_as) \
+	KASSERT(spin_is_locked(&(_as)->as_lock), ("ACL not locked!"))
+#if (defined(ATH_DEBUG_SPINLOCKS))
+#define	ACL_LOCK_CHECK(_as) do { \
+	if (spin_is_locked(&(_as)->as_lock)) \
+		printk("%s:%d - about to block on ACL lock!\n", __func__, __LINE__); \
+} while(0)
+#else /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#define	ACL_LOCK_CHECK(_as)
+#endif /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#else
+#define	ACL_LOCK_ASSERT(_as)
+#define	ACL_LOCK_CHECK(_as)
+#endif
+
+/*
+ * Per-node power-save queue definitions.  Beware of control
+ * flow with IEEE80211_NODE_SAVEQ_LOCK/IEEE80211_NODE_SAVEQ_UNLOCK.
+ */
+#define	IEEE80211_NODE_SAVEQ_INIT(_ni, _name) do {		\
+	skb_queue_head_init(&(_ni)->ni_savedq);			\
+} while (0)
+#define	IEEE80211_NODE_SAVEQ_DESTROY(_ni)
+#define	IEEE80211_NODE_SAVEQ_QLEN(_ni)		skb_queue_len(&(_ni)->ni_savedq)
+#define	IEEE80211_NODE_SAVEQ_LOCK_IRQ(_ni) do {			\
+	unsigned long __qlockflags;				\
+	IEEE80211_NODE_SAVEQ_LOCK_CHECK(_ni);		\
+	spin_lock_irqsave(&(_ni)->ni_savedq.lock, __qlockflags);
+#define	IEEE80211_NODE_SAVEQ_UNLOCK_IRQ(_ni)    		\
+	IEEE80211_NODE_SAVEQ_LOCK_ASSERT(_ni);			\
+	spin_unlock_irqrestore(&(_ni)->ni_savedq.lock, __qlockflags); \
+} while (0)
+#define	IEEE80211_NODE_SAVEQ_UNLOCK_IRQ_EARLY(_ni)		\
+	IEEE80211_NODE_SAVEQ_LOCK_ASSERT(_ni);			\
+	spin_unlock_irqrestore(&(_ni)->ni_savedq.lock, __qlockflags);
+
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+#define IEEE80211_NODE_SAVEQ_LOCK_ASSERT(_ni) \
+	KASSERT(spin_is_locked(&(_ni)->ni_savedq.lock), \
+		("node saveq not locked!"))
+#if (defined(ATH_DEBUG_SPINLOCKS))
+#define IEEE80211_NODE_SAVEQ_LOCK_CHECK(_ni) do { \
+	if (spin_is_locked(&(_ni)->ni_savedq.lock)) \
+		printk("%s:%d - about to block on node saveq lock!\n", __func__, __LINE__); \
+} while(0)
+#else /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#define IEEE80211_NODE_SAVEQ_LOCK_CHECK(_ni)
+#endif /* #if (defined(ATH_DEBUG_SPINLOCKS)) */
+#else
+#define IEEE80211_NODE_SAVEQ_LOCK_ASSERT(_ni)
+#define IEEE80211_NODE_SAVEQ_LOCK_CHECK(_ni)
+#endif
+
+/* caller MUST lock IEEE80211_NODE_SAVEQ */
+#define	IEEE80211_NODE_SAVEQ_DEQUEUE(_ni, _skb, _qlen) do {	\
+	_skb = __skb_dequeue(&(_ni)->ni_savedq);		\
+	(_qlen) = skb_queue_len(&(_ni)->ni_savedq);		\
+} while (0)
+#define	_IEEE80211_NODE_SAVEQ_ENQUEUE(_ni, _skb, _qlen, _age) do {	\
+	struct sk_buff *tail = skb_peek_tail(&(_ni)->ni_savedq);	\
+	if (tail != NULL) {						\
+		_age -= M_AGE_GET(tail);				\
+		__skb_queue_after(&(_ni)->ni_savedq, tail, _skb);	\
+	} else { 							\
+		__skb_queue_head(&(_ni)->ni_savedq, _skb);		\
+	}								\
+	M_AGE_SET(_skb, _age);						\
+	(_qlen) = skb_queue_len(&(_ni)->ni_savedq); 			\
+} while (0)
+
+/*
+ * Transmitted frames have the following information
+ * held in the sk_buff control buffer.  This is used to
+ * communicate various inter-procedural state that needs
+ * to be associated with the frame for the duration of
+ * its existence.
+ *
+ * NB: sizeof(cb) == 48 and the vlan code grabs the first
+ *     8 bytes so we reserve/avoid it.
+ */
+	struct ieee80211_cb {
+	u_int8_t vlan[8];			/* reserve for vlan tag info */
+	struct ieee80211_node *ni;
+	u_int32_t flags;
+#define	M_LINK0		0x01			/* frame needs WEP encryption */
+#define	M_FF		0x02			/* fast frame */
+#define	M_PWR_SAV	0x04			/* bypass power save handling */
+#define M_UAPSD		0x08			/* frame flagged for u-apsd handling */
+#define M_RAW           0x10
+#ifdef IEEE80211_DEBUG_REFCNT
+	int tracked;
+	void		(*next_destructor)(struct sk_buff *skb);
+#endif
+	struct sk_buff *next;			/* fast frame sk_buf chain */
+};
+
+
+#define	SKB_CB(_skb) 		((struct ieee80211_cb *)(_skb)->cb)
+
+#define M_FLAG_SET(_skb, _flag) \
+	(SKB_CB(_skb)->flags |= (_flag))
+#define	M_FLAG_CLR(_skb, _flag) \
+	(SKB_CB(_skb)->flags &= ~(_flag))
+#define	M_FLAG_GET(_skb, _flag) \
+	(SKB_CB(_skb)->flags & (_flag))
+#define M_FLAG_KEEP_ONLY(_skb, _flag) \
+	(SKB_CB(_skb)->flags &= (_flag))
+
+#define	M_PWR_SAV_SET(skb) M_FLAG_SET((skb), M_PWR_SAV)
+#define	M_PWR_SAV_CLR(skb) M_FLAG_CLR((skb), M_PWR_SAV)
+#define	M_PWR_SAV_GET(skb) M_FLAG_GET((skb), M_PWR_SAV)
+
+/*
+ * Skbufs on the power save queue are tagged with an age and
+ * timed out.  We reuse the hardware checksum field in the
+ * mbuf packet header to store this data.
+ * XXX use private cb area
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+#define skb_age csum_offset
+#else
+#define skb_age csum
+#endif
+
+#define	M_AGE_SET(skb,v)	(skb->skb_age = v)
+#define	M_AGE_GET(skb)		(skb->skb_age)
+#define	M_AGE_SUB(skb,adj)	(skb->skb_age -= adj)
+
+struct ieee80211com;
+struct ieee80211vap;
+
+int ieee80211_load_module(const char *);
+
+#define	le16toh(_x)	le16_to_cpu(_x)
+#define	htole16(_x)	cpu_to_le16(_x)
+#define	le32toh(_x)	le32_to_cpu(_x)
+#define	htole32(_x)	cpu_to_le32(_x)
+#define	be32toh(_x)	be32_to_cpu(_x)
+#define	htobe32(_x)	cpu_to_be32(_x)
+
+/*
+ * Linux has no equivalents to malloc types so null these out.
+ */
+#define	MALLOC_DEFINE(type, shortdesc, longdesc)
+#define	MALLOC_DECLARE(type)
+
+/*
+ * flags to malloc.
+ */
+#define	M_NOWAIT	0x0001		/* do not block */
+#define	M_WAITOK	0x0002		/* ok to block */
+#define	M_ZERO		0x0100		/* bzero the allocation */
+
+static __inline void *
+ieee80211_malloc(size_t size, int flags)
+{
+	void *p = kmalloc(size, flags & M_NOWAIT ? GFP_ATOMIC : GFP_KERNEL);
+	if (p && (flags & M_ZERO))
+		memset(p, 0, size);
+	return p;
+}
+#define	MALLOC(_ptr, cast, _size, _type, _flags) \
+	((_ptr) = (cast)ieee80211_malloc(_size, _flags))
+#define	FREE(addr, type)	kfree((addr))
+
+/*
+ * This unlikely to be popular but it dramatically reduces diffs.
+ */
+#define printf(...) printk(__VA_ARGS__)
+struct ieee80211com;
+extern void if_printf(struct net_device *, const char *, ...);
+
+/*
+ * Queue write-arounds and support routines.
+ */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_getmgtframe(_ppfrm, _pktlen) \
+	ieee80211_getmgtframe_debug(_ppfrm, _pktlen, __func__, __LINE__)
+extern struct sk_buff * ieee80211_getmgtframe_debug(u_int8_t **frm, u_int pktlen, 
+						    const char* func, int line);
+#else
+extern struct sk_buff * ieee80211_getmgtframe(u_int8_t **frm, u_int pktlen);
+#endif
+
+#define	IF_ENQUEUE(_q,_skb)	skb_queue_tail(_q, _skb)
+#define	IF_DEQUEUE(_q,_skb)	(_skb = skb_dequeue(_q))
+#define	_IF_QLEN(_q)		skb_queue_len(_q)
+#define	IF_DRAIN(_q)		skb_queue_drain(_q)
+extern	void skb_queue_drain(struct sk_buff_head *q);
+
+#ifndef __MOD_INC_USE_COUNT
+#define	_MOD_INC_USE(_m, _err)						\
+	if (!try_module_get(_m)) {					\
+		printk(KERN_WARNING "%s: try_module_get failed\n",	\
+			__func__); 					\
+		_err;							\
+	}
+#define	_MOD_DEC_USE(_m)		module_put(_m)
+#else
+#define	_MOD_INC_USE(_m, _err)	MOD_INC_USE_COUNT
+#define	_MOD_DEC_USE(_m)	MOD_DEC_USE_COUNT
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static __inline u_int64_t
+get_jiffies_64(void)
+{
+	return (u_int64_t) jiffies;		/* XXX not right */
+}
+#endif
+
+/* msecs_to_jiffies appeared in 2.6.7 and 2.4.29 */
+#include <linux/delay.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \
+	 LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) || \
+	LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29)
+
+/* The following definitions and inline functions are
+ * copied from the kernel src, include/linux/jiffies.h */
+
+#ifndef MSEC_PER_SEC
+#define MSEC_PER_SEC (1000L)
+#endif
+
+#ifndef MAX_JIFFY_OFFSET
+#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+#endif
+
+static __inline unsigned int jiffies_to_msecs(const unsigned long j)
+{
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+	return (MSEC_PER_SEC / HZ) * j;
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+	return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
+#else
+	return (j * MSEC_PER_SEC) / HZ;
+#endif
+}
+
+static __inline unsigned long msecs_to_jiffies(const unsigned int m)
+{
+	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+	return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+	return m * (HZ / MSEC_PER_SEC);
+#else
+	return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
+#endif
+}
+
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7)
+#include <linux/jiffies.h>
+#endif
+
+#ifndef CLONE_KERNEL
+/*
+ * List of flags we want to share for kernel threads,
+ * if only because they are not used by them anyway.
+ */
+#define CLONE_KERNEL	(CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
+#endif
+
+#include <linux/mm.h>
+#ifndef offset_in_page
+#define	offset_in_page(p) ((unsigned long) (p) & ~PAGE_MASK)
+#endif
+
+#ifndef module_put_and_exit
+#define module_put_and_exit(code) do {	\
+	_MOD_DEC_USE(THIS_MODULE);	\
+	do_exit(code);			\
+} while (0)
+#endif
+
+/*
+ * Linux uses __BIG_ENDIAN and __LITTLE_ENDIAN while BSD uses _foo
+ * and an explicit _BYTE_ORDER.  Sorry, BSD got there first--define
+ * things in the BSD way...
+ */
+#undef _LITTLE_ENDIAN
+#define	_LITTLE_ENDIAN	1234	/* LSB first: i386, vax */
+#undef _BIG_ENDIAN
+#define	_BIG_ENDIAN	4321	/* MSB first: 68000, ibm, net */
+#include <asm/byteorder.h>
+#if defined(__LITTLE_ENDIAN)
+#define	_BYTE_ORDER	_LITTLE_ENDIAN
+#elif defined(__BIG_ENDIAN)
+#define	_BYTE_ORDER	_BIG_ENDIAN
+#else
+#error "Please fix asm/byteorder.h"
+#endif
+
+
+/*
+ * Deal with the sysctl handler api changing.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
+#define	IEEE80211_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \
+	f(ctl_table *ctl, int write, struct file *filp, \
+	  void __user *buffer, size_t *lenp)
+#define	IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
+	proc_dointvec(ctl, write, filp, buffer, lenp)
+#else
+#define	IEEE80211_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \
+	f(ctl_table *ctl, int write, struct file *filp, \
+	  void __user *buffer, size_t *lenp, loff_t *ppos)
+#define	IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
+	proc_dointvec(ctl, write, filp, buffer, lenp, ppos)
+#endif
+
+void ieee80211_virtfs_latevattach(struct ieee80211vap *);
+void ieee80211_virtfs_vdetach(struct ieee80211vap *);
+int ieee80211_proc_vcreate(struct ieee80211vap *, struct file_operations *,
+	       char *);
+void ieee80211_proc_cleanup(struct ieee80211vap *);
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define IEEE80211_VLAN_TAG_USED 1
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)
+#define	vlan_hwaccel_receive_skb(skb, grp, tag)	vlan_hwaccel_rx(skb, grp, tag)
+#endif
+
+#ifndef VLAN_GROUP_ARRAY_PART_LEN
+#define vlan_group_set_device(group, vid, dev) do { \
+	group->vlan_devices[vid] = dev; \
+} while (0);
+#endif
+
+#else
+#define IEEE80211_VLAN_TAG_USED 0
+#endif
+void ieee80211_vlan_vattach(struct ieee80211vap *);
+void ieee80211_vlan_vdetach(struct ieee80211vap *);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#define	free_netdev(dev)	kfree(dev)
+#endif
+
+void ieee80211_ioctl_vattach(struct ieee80211vap *);
+void ieee80211_ioctl_vdetach(struct ieee80211vap *);
+struct ifreq;
+int ieee80211_ioctl_create_vap(struct ieee80211com *, struct ifreq *,
+	struct net_device *);
+struct ieee80211vap *ieee80211_create_vap(struct ieee80211com *, char *,
+	struct net_device *, int, int);
+#endif /* _NET80211_IEEE80211_LINUX_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_monitor.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_monitor.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_monitor.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_monitor.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 2005 John Bicket
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_monitor.h 3014 2007-12-10 23:13:33Z scottr $
+ */
+#ifndef _NET80211_IEEE80211_MONITOR_H_
+#define _NET80211_IEEE80211_MONITOR_H_
+
+#ifndef ARPHRD_IEEE80211_RADIOTAP
+#define ARPHRD_IEEE80211_RADIOTAP	803 /* IEEE 802.11 + radiotap header */
+#endif /* ARPHRD_IEEE80211_RADIOTAP */
+
+#ifndef ARPHRD_IEEE80211_ATHDESC
+#define ARPHRD_IEEE80211_ATHDESC	804 /* IEEE 802.11 + atheros descriptor */
+#endif /* ARPHRD_IEEE80211_RADIOTAP */
+
+#define ATHDESC_HEADER_SIZE	32
+
+#include <net80211/ieee80211_radiotap.h>
+#include <ah_desc.h>
+#include <ath/if_athvar.h>
+
+struct ieee80211_phy_params {
+	u_int8_t rate0;
+	u_int8_t rate1;
+	u_int8_t rate2;
+	u_int8_t rate3;
+
+	u_int8_t try0;
+	u_int8_t try1;
+	u_int8_t try2;
+	u_int8_t try3;
+
+	u_int8_t power;
+	u_int32_t flags;
+};
+
+enum {
+	DIDmsg_lnxind_wlansniffrm		= 0x00000044,
+	DIDmsg_lnxind_wlansniffrm_hosttime	= 0x00010044,
+	DIDmsg_lnxind_wlansniffrm_mactime	= 0x00020044,
+	DIDmsg_lnxind_wlansniffrm_channel	= 0x00030044,
+	DIDmsg_lnxind_wlansniffrm_rssi		= 0x00040044,
+	DIDmsg_lnxind_wlansniffrm_sq		= 0x00050044,
+	DIDmsg_lnxind_wlansniffrm_signal	= 0x00060044,
+	DIDmsg_lnxind_wlansniffrm_noise		= 0x00070044,
+	DIDmsg_lnxind_wlansniffrm_rate		= 0x00080044,
+	DIDmsg_lnxind_wlansniffrm_istx		= 0x00090044,
+	DIDmsg_lnxind_wlansniffrm_frmlen	= 0x000A0044
+};
+enum {
+	P80211ENUM_msgitem_status_no_value	= 0x00
+};
+enum {
+	P80211ENUM_truth_false			= 0x00,
+	P80211ENUM_truth_true			= 0x01
+};
+
+struct p80211item_uint32 {
+	u_int32_t did;
+	u_int16_t status;
+	u_int16_t len;
+	u_int32_t data;
+};
+
+struct wlan_ng_prism2_header {
+	u_int32_t msgcode;
+	u_int32_t msglen;
+#define WLAN_DEVNAMELEN_MAX 16
+	u_int8_t devname[WLAN_DEVNAMELEN_MAX];
+	struct p80211item_uint32 hosttime;
+	struct p80211item_uint32 mactime;
+	struct p80211item_uint32 channel;
+	struct p80211item_uint32 rssi;
+	struct p80211item_uint32 sq;
+	struct p80211item_uint32 signal;
+	struct p80211item_uint32 noise;
+	struct p80211item_uint32 rate;
+	struct p80211item_uint32 istx;
+	struct p80211item_uint32 frmlen;
+};
+
+#define ATH_RX_RADIOTAP_PRESENT (               \
+	(1 << IEEE80211_RADIOTAP_TSFT)		| \
+	(1 << IEEE80211_RADIOTAP_FLAGS)         | \
+	(1 << IEEE80211_RADIOTAP_RATE)          | \
+	(1 << IEEE80211_RADIOTAP_CHANNEL)       | \
+	(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)	| \
+	(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)	| \
+	(1 << IEEE80211_RADIOTAP_ANTENNA)       | \
+	(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)  | \
+	0)
+
+struct ath_rx_radiotap_header {
+	struct ieee80211_radiotap_header wr_ihdr;
+	__le64		wr_tsft;
+	u_int8_t	wr_flags;
+	u_int8_t	wr_rate;
+	__le16		wr_chan_freq;
+	__le16		wr_chan_flags;
+	int8_t		wr_dbm_antsignal;
+	int8_t		wr_dbm_antnoise;
+	u_int8_t	wr_antenna;
+	u_int8_t	wr_antsignal;
+}__attribute__((__packed__));
+
+#define ATH_TX_RADIOTAP_PRESENT (               \
+	(1 << IEEE80211_RADIOTAP_TSFT)		| \
+	(1 << IEEE80211_RADIOTAP_FLAGS)         | \
+	(1 << IEEE80211_RADIOTAP_RATE)          | \
+	(1 << IEEE80211_RADIOTAP_ANTENNA)       | \
+	(1 << IEEE80211_RADIOTAP_TX_FLAGS)	| \
+	(1 << IEEE80211_RADIOTAP_DATA_RETRIES)	| \
+	0)
+
+struct ath_tx_radiotap_header {
+	struct ieee80211_radiotap_header wt_ihdr;
+	__le64		wt_tsft;
+	u_int8_t	wt_flags;
+	u_int8_t	wt_rate;
+	u_int8_t	wt_antenna;
+	u_int8_t	wt_pad; /* Padding to ensure txflags is aligned */
+	__le16		wt_txflags;
+	u_int8_t	wt_dataretries;
+}__attribute__((__packed__));
+
+/*
+ * Dispatch an skb to monitor-mode VAPs.  The skb is assumed
+ * to have space at the front to push a wlan_ng_prims2_header.
+ */
+void ieee80211_input_monitor(struct ieee80211com *, struct sk_buff *,
+	const struct ath_buf *, int, u_int64_t, struct ath_softc *);
+
+
+void ieee80211_monitor_encap(struct ieee80211vap *, struct sk_buff *);
+
+
+#endif /* _NET80211_IEEE80211_MONITOR_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_node.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_node.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_node.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_node.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,434 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_node.h 3268 2008-01-26 20:48:11Z mtaylor $
+ */
+#ifndef _NET80211_IEEE80211_NODE_H_
+#define _NET80211_IEEE80211_NODE_H_
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>		/* for ieee80211_nodestats */
+#include <net80211/ieee80211_proto.h>		/* for proto macros on node */
+
+/*
+ * Each ieee80211com instance has a single timer that fires once a
+ * second.  This is used to initiate various work depending on the
+ * state of the instance: scanning (passive or active), ``transition''
+ * (waiting for a response to a management frame when operating
+ * as a station), and node inactivity processing (when operating
+ * as an AP).  For inactivity processing each node has a timeout
+ * set in its ni_inact field that is decremented on each timeout
+ * and the node is reclaimed when the counter goes to zero.  We
+ * use different inactivity timeout values depending on whether
+ * the node is associated and authorized (either by 802.1x or
+ * open/shared key authentication) or associated but yet to be
+ * authorized.  The latter timeout is shorter to more aggressively
+ * reclaim nodes that leave part way through the 802.1x exchange.
+ */
+#define	IEEE80211_INACT_WAIT	15				/* inactivity interval (secs) */
+#define	IEEE80211_INACT_INIT	(30/IEEE80211_INACT_WAIT)	/* initial */
+#define	IEEE80211_INACT_AUTH	(180/IEEE80211_INACT_WAIT)	/* associated but not authorized */
+#define	IEEE80211_INACT_RUN	(300/IEEE80211_INACT_WAIT)	/* authorized */
+#define	IEEE80211_INACT_PROBE	(30/IEEE80211_INACT_WAIT)	/* probe */
+#define	IEEE80211_INACT_SCAN	(300/IEEE80211_INACT_WAIT)	/* scanned */
+
+#define	IEEE80211_TRANS_WAIT 	5				/* mgt frame tx timer (secs) */
+
+#define	IEEE80211_NODE_HASHSIZE	32
+/* simple hash is enough for variation of macaddr */
+#define	IEEE80211_NODE_HASH(addr)	\
+	(((const u_int8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % \
+		IEEE80211_NODE_HASHSIZE)
+
+struct ieee80211_rsnparms {
+	u_int8_t rsn_mcastcipher;	/* mcast/group cipher */
+	u_int8_t rsn_mcastkeylen;	/* mcast key length */
+	u_int8_t rsn_ucastcipherset;	/* unicast cipher set */
+	u_int8_t rsn_ucastcipher;	/* selected unicast cipher */
+	u_int8_t rsn_ucastkeylen;	/* unicast key length */
+	u_int8_t rsn_keymgmtset;	/* key management algorithms */
+	u_int8_t rsn_keymgmt;		/* selected key mgmt algo */
+	u_int16_t rsn_caps;		/* capabilities */
+};
+
+struct ieee80211_node_table;
+struct ieee80211com;
+struct ieee80211vap;
+struct ath_buf;
+struct ath_softc;
+
+/*
+ * Node specific information.  Note that drivers are expected
+ * to derive from this structure to add device-specific per-node
+ * state.  This is done by overriding the ic_node_* methods in
+ * the ieee80211com structure.
+ */
+struct ieee80211_node {
+	struct ieee80211vap *ni_vap;
+	struct ieee80211com *ni_ic;
+	struct ieee80211_node_table *ni_table;
+	TAILQ_ENTRY(ieee80211_node) ni_list;
+	LIST_ENTRY(ieee80211_node) ni_hash;
+	atomic_t ni_refcnt;
+	u_int ni_scangen;			/* gen# for timeout scan */
+	u_int8_t ni_authmode;			/* authentication algorithm */
+	u_int16_t ni_flags;			/* special-purpose state */
+#define	IEEE80211_NODE_AUTH	0x0001		/* authorized for data */
+#define	IEEE80211_NODE_QOS	0x0002		/* QoS enabled */
+#define	IEEE80211_NODE_ERP	0x0004		/* ERP enabled */
+/* NB: this must have the same value as IEEE80211_FC1_PWR_MGT */
+#define	IEEE80211_NODE_PWR_MGT	0x0010		/* power save mode enabled */
+#define	IEEE80211_NODE_AREF	0x0020		/* authentication ref held */
+#define IEEE80211_NODE_UAPSD	0x0040		/* U-APSD power save enabled */
+#define IEEE80211_NODE_UAPSD_TRIG 0x0080	/* U-APSD triggerable state */
+#define IEEE80211_NODE_UAPSD_SP	0x0100		/* U-APSD SP in progress */
+#define IEEE80211_NODE_PS_CHANGED	0x0200	/* PS state change */
+	u_int8_t ni_ath_flags;			/* Atheros feature flags */
+	/* NB: These must have the same values as IEEE80211_ATHC_* */
+#define IEEE80211_NODE_TURBOP	0x0001		/* Turbo prime enable */
+#define IEEE80211_NODE_COMP	0x0002		/* Compresssion enable */
+#define IEEE80211_NODE_FF	0x0004          /* Fast Frame capable */
+#define IEEE80211_NODE_XR	0x0008		/* Atheros WME enable */
+#define IEEE80211_NODE_AR	0x0010		/* AR capable */
+#define IEEE80211_NODE_BOOST	0x0080
+	u_int16_t ni_ath_defkeyindex;		/* Atheros def key index */
+#define IEEE80211_INVAL_DEFKEY	0x7FFF
+	u_int16_t ni_associd;			/* assoc response */
+	u_int16_t ni_txpower;			/* current transmit power (in 0.5 dBm) */
+	u_int16_t ni_vlan;			/* vlan tag */
+	u_int32_t *ni_challenge;		/* shared-key challenge */
+	u_int8_t *ni_wpa_ie;			/* captured WPA ie */
+	u_int8_t *ni_rsn_ie;			/* captured RSN ie */
+	u_int8_t *ni_wme_ie;			/* captured WME ie */
+	u_int8_t *ni_ath_ie;			/* captured Atheros ie */
+	u_int8_t *ni_suppchans;			/* supported channels */
+	u_int8_t *ni_suppchans_new;		/* supported channels of ongoing association */
+	u_int8_t *ni_needed_chans;		/* nodes which don't support these will be removed */
+	u_int8_t ni_n_needed_chans;		/* size of ni_needed_chans list */
+	u_int16_t ni_txseqs[17];		/* tx seq per-tid */
+	u_int16_t ni_rxseqs[17];		/* rx seq previous per-tid*/
+	u_int32_t ni_rxfragstamp;		/* time stamp of last rx frag */
+	struct sk_buff *ni_rxfrag;		/* rx frag reassembly */
+	struct ieee80211_rsnparms ni_rsn;	/* RSN/WPA parameters */
+	struct ieee80211_key ni_ucastkey;	/* unicast key */
+	int ni_rxkeyoff;    			/* Receive key offset */
+
+	/* hardware */
+	u_int64_t ni_rtsf;			/* recv timestamp */
+	u_int32_t ni_last_rx;			/* recv jiffies */
+	u_int8_t ni_rssi;			/* recv ssi */
+
+	/* header */
+	u_int8_t ni_macaddr[IEEE80211_ADDR_LEN];
+	u_int8_t ni_bssid[IEEE80211_ADDR_LEN];
+
+	/* beacon, probe response */
+	union {
+		u_int8_t data[8];
+		__le64 tsf;
+	} ni_tstamp;				/* from last rcv'd beacon */
+
+	u_int16_t ni_intval;			/* beacon interval */
+	u_int16_t ni_intval_old;		/* beacon interval before first change */
+	u_int16_t ni_intval_cnt;		/* count of ni_intval != ni_intval_old */
+	unsigned long ni_intval_end;		/* end of transition interval jiffies */
+
+	u_int16_t ni_capinfo;			/* capabilities */
+	u_int8_t ni_esslen;
+	u_int8_t ni_essid[IEEE80211_NWID_LEN];
+	struct ieee80211_rateset ni_rates;	/* negotiated rate set */
+	struct ieee80211_channel *ni_chan;
+	u_int16_t ni_fhdwell;			/* FH only */
+	u_int8_t ni_fhindex;			/* FH only */
+	u_int8_t ni_erp;			/* ERP from beacon/probe resp */
+	u_int16_t ni_timoff;			/* byte offset to TIM ie */
+
+	/* others */
+	struct sk_buff_head ni_savedq;		/* packets queued for pspoll */
+	short ni_inact;				/* inactivity mark count */
+	short ni_inact_reload;			/* inactivity reload value */
+	int ni_txrate;				/* index to ni_rates[] */
+	struct ieee80211_nodestats ni_stats;	/* per-node statistics */
+	struct ieee80211vap *ni_prev_vap;  	/* previously associated vap */
+	u_int8_t ni_uapsd;			/* U-APSD per-node flags matching WMM STA Qos Info field */
+	u_int8_t ni_uapsd_maxsp; 		/* maxsp from flags above */
+	u_int16_t ni_uapsd_trigseq[WME_NUM_AC];	/* trigger suppression on retry */
+	__le16 ni_pschangeseq;
+};
+MALLOC_DECLARE(M_80211_NODE);
+
+#define	IEEE80211_NODE_AID(ni)			IEEE80211_AID(ni->ni_associd)
+
+#define	IEEE80211_NODE_STAT(ni,stat)		(ni->ni_stats.ns_##stat++)
+#define	IEEE80211_NODE_STAT_ADD(ni,stat,v)	(ni->ni_stats.ns_##stat += v)
+#define	IEEE80211_NODE_STAT_SET(ni,stat,v)	(ni->ni_stats.ns_##stat = v)
+
+#define WME_UAPSD_AC_CAN_TRIGGER(_ac, _ni) (				\
+		((_ni)->ni_flags & IEEE80211_NODE_UAPSD_TRIG) &&	\
+		WME_UAPSD_AC_ENABLED((_ac), (_ni)->ni_uapsd))
+#define WME_UAPSD_NODE_MAXQDEPTH	8
+#define IEEE80211_NODE_UAPSD_USETIM(_ni) (((_ni)->ni_uapsd & 0xF) == 0xF)
+#define WME_UAPSD_NODE_INVALIDSEQ	0xffff
+#define WME_UAPSD_NODE_TRIGSEQINIT(_ni)					\
+		(memset(&(_ni)->ni_uapsd_trigseq[0],			\
+		 0xff, sizeof((_ni)->ni_uapsd_trigseq)))
+
+void ieee80211_node_attach(struct ieee80211com *);
+void ieee80211_node_detach(struct ieee80211com *);
+void ieee80211_node_vattach(struct ieee80211vap *);
+void ieee80211_node_latevattach(struct ieee80211vap *);
+void ieee80211_node_vdetach(struct ieee80211vap *);
+
+static __inline int
+ieee80211_node_is_authorized(const struct ieee80211_node *ni)
+{
+	return (ni->ni_flags & IEEE80211_NODE_AUTH);
+}
+
+void ieee80211_node_authorize(struct ieee80211_node *);
+void ieee80211_node_unauthorize(struct ieee80211_node *);
+
+void ieee80211_create_ibss(struct ieee80211vap *, struct ieee80211_channel *);
+void ieee80211_reset_bss(struct ieee80211vap *);
+int ieee80211_ibss_merge(struct ieee80211_node *);
+struct ieee80211_scan_entry;
+int ieee80211_sta_join(struct ieee80211vap *, const struct ieee80211_scan_entry *);
+void ieee80211_sta_join1_tasklet(IEEE80211_TQUEUE_ARG);
+void ieee80211_sta_leave(struct ieee80211_node *);
+
+#define WDS_AGING_TIME		600   /* 10 minutes */
+#define WDS_AGING_COUNT 	2
+#define WDS_AGING_STATIC 	0xffff
+#define WDS_AGING_TIMER_VAL 	(WDS_AGING_TIME / 2)
+
+struct ieee80211_wds_addr {
+	LIST_ENTRY(ieee80211_wds_addr) wds_hash;
+	u_int8_t	wds_macaddr[IEEE80211_ADDR_LEN];
+	struct ieee80211_node *wds_ni;
+	u_int16_t wds_agingcount;
+};
+
+/*
+ * Table of ieee80211_node instances.  Each ieee80211com
+ * has at least one for holding the scan candidates.
+ * When operating as an access point or in ibss mode there
+ * is a second table for associated stations or neighbors.
+ */
+struct ieee80211_node_table {
+	const char *nt_name;			/* for debugging */
+	struct ieee80211com *nt_ic;		/* back reference */
+	ieee80211_node_table_lock_t nt_nodelock;	/* on node table */
+	TAILQ_HEAD(, ieee80211_node) nt_node;	/* information of all nodes */
+	ATH_LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE];
+	ATH_LIST_HEAD(, ieee80211_wds_addr) nt_wds_hash[IEEE80211_NODE_HASHSIZE];
+	ieee80211_scan_lock_t nt_scanlock;	/* on nt_scangen */
+	u_int nt_scangen;			/* gen# for timeout scan */
+	int nt_inact_init;			/* initial node inact setting */
+	struct timer_list nt_wds_aging_timer;	/* timer to age out wds entries */
+};
+
+/* Allocates a new ieee80211_node* that has a reference count of one, and 
+ * adds it to the node table. */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_alloc_node_table(_vap, _mac) \
+	ieee80211_alloc_node_table_debug(_vap, _mac, __func__, __LINE__)
+struct ieee80211_node *ieee80211_alloc_node_table_debug(struct ieee80211vap *,
+	const u_int8_t *, const char* name, int line);
+#else
+struct ieee80211_node *ieee80211_alloc_node_table(struct ieee80211vap *,
+	const u_int8_t *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Allocates a new ieee80211_node* that has a reference count.  
+ * If tmp is 0, it is added to the node table and the reference is used.
+ * If tmp is 1, then the caller gets to use the reference. */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_dup_bss(_vap, _mac, _tmp) \
+	ieee80211_dup_bss_debug(_vap, _mac, _tmp, __func__, __LINE__)
+struct ieee80211_node *ieee80211_dup_bss_debug(struct ieee80211vap *,
+	const u_int8_t *, unsigned char tmp, const char*, int);
+#else
+struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *,
+	const u_int8_t *, unsigned char tmp);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+void ieee80211_node_reset(struct ieee80211_node *, struct ieee80211vap *);
+
+/* Returns a ieee80211_node* with refcount incremented, if found */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define	ieee80211_find_node(_nt, _mac) \
+	ieee80211_find_node_debug(_nt, _mac, __func__, __LINE__)
+struct ieee80211_node *ieee80211_find_node_debug(struct ieee80211_node_table *,
+	const u_int8_t *, const char *, int);
+#else
+struct ieee80211_node *ieee80211_find_node(struct ieee80211_node_table *,
+	const u_int8_t *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Returns a ieee80211_node* with refcount incremented, if found */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define	ieee80211_find_rxnode(_nt, _wh) \
+	ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__)
+struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *,
+	const struct ieee80211_frame_min *, const char *, int);
+#else
+struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,
+	const struct ieee80211_frame_min *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Returns a ieee80211_node* with refcount incremented, if found */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define	ieee80211_find_txnode(_nt, _mac) \
+	ieee80211_find_txnode_debug(_nt, _mac, __func__, __LINE__)
+struct ieee80211_node *ieee80211_find_txnode_debug(struct ieee80211vap *,
+	const u_int8_t *, const char *, int);
+#else
+struct ieee80211_node *ieee80211_find_txnode(struct ieee80211vap *,
+	const u_int8_t *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_free_node(_ni) \
+	ieee80211_free_node_debug(_ni, __func__, __LINE__)
+void ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line);
+#else
+void ieee80211_free_node(struct ieee80211_node *ni);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Reference counting only needs to be locked out against the transitions,
+ * 0->1 and 1->0 (i.e., when we do not own the reference we are getting).
+ * This only happens when finding the a node reference from the node table,
+ * which is locked seperately. Thus, we do not need to lock the follwoing 
+ * functions. 
+ * Increment the reference counter for ieee80211_node*
+ */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_ref_node(_ni) \
+	ieee80211_ref_node_debug(_ni, __func__, __LINE__)
+struct ieee80211_node *
+ieee80211_ref_node_debug(struct ieee80211_node *ni, const char *func, int line);
+#else
+struct ieee80211_node *
+ieee80211_ref_node(struct ieee80211_node *ni);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+#define PASS_NODE(_ni) \
+	ieee80211_pass_node(&_ni)
+
+static __inline struct ieee80211_node *
+ieee80211_pass_node(struct ieee80211_node **pni) {
+	struct ieee80211_node *tmp = *pni;
+	*pni = NULL;
+	return (tmp);
+}
+
+/* Decrement ieee80211_node* refcount, and relinquish the pointer. */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_unref_node(_pni) \
+	ieee80211_unref_node_debug(_pni, __func__, __LINE__)
+void
+ieee80211_unref_node_debug(struct ieee80211_node **pni, const char *func, int line);
+#else
+void
+ieee80211_unref_node(struct ieee80211_node **pni);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Increments reference count of ieee80211_node *ni */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_add_wds_addr(_table, _node, _mac, _static) \
+	ieee80211_add_wds_addr_debug(_table, _node, _mac, _static, __func__, __LINE__)
+int ieee80211_add_wds_addr_debug(struct ieee80211_node_table *, struct ieee80211_node *,
+	const u_int8_t *, u_int8_t, const char* func, int line);
+#else
+int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *,
+	const u_int8_t *, u_int8_t);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Decrements reference count of ieee80211_node *ni */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_remove_wds_addr(_table, _mac) \
+	ieee80211_remove_wds_addr_debug(_table, _mac, __func__, __LINE__)
+void ieee80211_remove_wds_addr_debug(struct ieee80211_node_table *, const u_int8_t *,
+			       const char* func, int line);
+#else
+void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Decrements reference count of node, if found */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_del_wds_node(_table, _node) \
+	ieee80211_del_wds_node_debug(_table, _node, __func__, __LINE__)
+void ieee80211_del_wds_node_debug(struct ieee80211_node_table *, struct ieee80211_node *,
+			    const char* func, int line);
+#else
+void ieee80211_del_wds_node(struct ieee80211_node_table *, struct ieee80211_node *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/* Increments reference count of node, if found */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_find_wds_node(_table, _mac) \
+	ieee80211_find_wds_node_debug(_table, _mac, __func__, __LINE__)
+struct ieee80211_node *ieee80211_find_wds_node_debug(struct ieee80211_node_table *,
+	const u_int8_t *, const char* func, int line);
+#else
+struct ieee80211_node *ieee80211_find_wds_node(struct ieee80211_node_table *,
+	const u_int8_t *);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+typedef void ieee80211_iter_func(void *, struct ieee80211_node *);
+void ieee80211_iterate_nodes(struct ieee80211_node_table *,
+	ieee80211_iter_func *, void *);
+void ieee80211_iterate_dev_nodes(struct net_device *,
+	struct ieee80211_node_table *, ieee80211_iter_func *, void *);
+void	ieee80211_dump_node(struct ieee80211_node_table *,
+	struct ieee80211_node *);
+void	ieee80211_dump_nodes(struct ieee80211_node_table *);
+/* Returns a node with refcount of one.  Caller must release that reference */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_fakeup_adhoc_node(_vap, _mac) \
+	ieee80211_fakeup_adhoc_node_debug(_vap, _mac, __func__, __LINE__)
+struct ieee80211_node *ieee80211_fakeup_adhoc_node_debug(struct ieee80211vap *,
+	const u_int8_t macaddr[], const char*, int);
+#else
+struct ieee80211_node *ieee80211_fakeup_adhoc_node(struct ieee80211vap *,
+	const u_int8_t macaddr[]);
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+struct ieee80211_scanparams;
+/* Returns a node with refcount of one.  Caller must release that reference */
+struct ieee80211_node *ieee80211_add_neighbor(struct ieee80211vap *,
+	const struct ieee80211_frame *, const struct ieee80211_scanparams *);
+/* Increments reference count of node */
+void ieee80211_node_join(struct ieee80211_node *, int);
+/* Decrements reference count of node */
+void ieee80211_node_leave(struct ieee80211_node *);
+u_int8_t ieee80211_getrssi(struct ieee80211com *);
+int32_t ieee80211_get_node_count(struct ieee80211com *);
+#endif /* _NET80211_IEEE80211_NODE_H_ */
+
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_power.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_power.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_power.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_power.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_power.h 3075 2007-12-23 20:11:05Z mentor $
+ */
+#ifndef _NET80211_IEEE80211_POWER_H_
+#define _NET80211_IEEE80211_POWER_H_
+
+struct ieee80211com;
+struct ieee80211vap;
+
+void	ieee80211_power_attach(struct ieee80211com *);
+void	ieee80211_power_detach(struct ieee80211com *);
+void	ieee80211_power_vattach(struct ieee80211vap *);
+void	ieee80211_power_latevattach(struct ieee80211vap *);
+void	ieee80211_power_vdetach(struct ieee80211vap *);
+
+struct ieee80211_node;
+
+int	ieee80211_node_saveq_drain(struct ieee80211_node *);
+int	ieee80211_node_saveq_age(struct ieee80211_node *);
+int	ieee80211_pwrsave(struct sk_buff *);
+void	ieee80211_node_pwrsave(struct ieee80211_node *, int);
+void	ieee80211_sta_pwrsave(struct ieee80211vap *, int);
+#endif /* _NET80211_IEEE80211_POWER_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_proto.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_proto.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_proto.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_proto.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,308 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_proto.h 3268 2008-01-26 20:48:11Z mtaylor $
+ */
+#ifndef _NET80211_IEEE80211_PROTO_H_
+#define _NET80211_IEEE80211_PROTO_H_
+
+/*
+ * 802.11 protocol implementation definitions.
+ */
+
+enum ieee80211_state {
+	IEEE80211_S_INIT	= 0,	/* default state */
+	IEEE80211_S_SCAN	= 1,	/* scanning */
+	IEEE80211_S_AUTH	= 2,	/* try to authenticate */
+	IEEE80211_S_ASSOC	= 3,	/* try to assoc */
+	IEEE80211_S_RUN		= 4,	/* associated */
+};
+#define	IEEE80211_S_MAX		(IEEE80211_S_RUN + 1)
+
+#define	IEEE80211_SEND_MGMT(_ni,_type,_arg) \
+	((*(_ni)->ni_ic->ic_send_mgmt)(_ni, _type, _arg))
+
+extern const char *ieee80211_mgt_subtype_name[];
+extern const char *ieee80211_ctl_subtype_name[];
+extern const char *ieee80211_state_name[IEEE80211_S_MAX];
+extern const char *ieee80211_wme_acnames[];
+extern const char *ieee80211_phymode_name[];
+
+void ieee80211_proto_attach(struct ieee80211com *);
+void ieee80211_proto_detach(struct ieee80211com *);
+void ieee80211_proto_vattach(struct ieee80211vap *);
+void ieee80211_proto_vdetach(struct ieee80211vap *);
+
+struct ieee80211_node;
+struct ieee80211_channel *ieee80211_doth_findchan(struct ieee80211vap *, u_int8_t);
+int ieee80211_input(struct ieee80211vap *, struct ieee80211_node *, struct sk_buff *, int, u_int64_t);
+int ieee80211_input_all(struct ieee80211com *, struct sk_buff *, int, u_int64_t);
+int ieee80211_setup_rates(struct ieee80211_node *, const u_int8_t *,
+	const u_int8_t *, int);
+void ieee80211_saveie(u_int8_t **, const u_int8_t *);
+void ieee80211_saveath(struct ieee80211_node *, u_int8_t *);
+void ieee80211_recv_mgmt(struct ieee80211vap *, struct ieee80211_node *,
+	struct sk_buff *, int, int, u_int64_t);
+void ieee80211_sta_pwrsave(struct ieee80211vap *, int);
+int ieee80211_hardstart(struct sk_buff *, struct net_device *);
+void ieee80211_parent_queue_xmit(struct sk_buff *);
+int ieee80211_send_nulldata(struct ieee80211_node *);
+int ieee80211_send_qosnulldata(struct ieee80211_node *, int);
+int ieee80211_send_mgmt(struct ieee80211_node *, int, int);
+int ieee80211_send_probereq(struct ieee80211_node *,
+	const u_int8_t sa[IEEE80211_ADDR_LEN],
+	const u_int8_t da[IEEE80211_ADDR_LEN],
+	const u_int8_t bssid[IEEE80211_ADDR_LEN],
+	const u_int8_t *, size_t, const void *, size_t);
+struct sk_buff *ieee80211_encap(struct ieee80211_node *, struct sk_buff *, int *);
+
+void ieee80211_reset_erp(struct ieee80211com *, enum ieee80211_phymode);
+void ieee80211_set_shortslottime(struct ieee80211com *, int);
+int ieee80211_iserp_rateset(struct ieee80211com *, struct ieee80211_rateset *);
+void ieee80211_set11gbasicrates(struct ieee80211_rateset *, enum ieee80211_phymode);
+enum ieee80211_phymode ieee80211_get11gbasicrates(struct ieee80211_rateset *);
+void ieee80211_send_pspoll(struct ieee80211_node *);
+void ieee80211_check_mic(struct ieee80211_node *, struct sk_buff *);
+
+/*
+ * Return the size of the 802.11 header for a management or data frame.
+ */
+static __inline int
+ieee80211_hdrsize(const void *data)
+{
+	const struct ieee80211_frame *wh = data;
+	int size = sizeof(struct ieee80211_frame);
+
+	/* NB: we don't handle control frames */
+	KASSERT((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL,
+		("%s: control frame", __func__));
+	if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
+		size += IEEE80211_ADDR_LEN;
+	if (IEEE80211_QOS_HAS_SEQ(wh))
+		size += sizeof(u_int16_t);
+	return size;
+}
+
+/*
+ * Like ieee80211_hdrsize, but handles any type of frame.
+ */
+static __inline int
+ieee80211_anyhdrsize(const void *data)
+{
+	const struct ieee80211_frame *wh = data;
+
+	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) {
+		switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
+		case IEEE80211_FC0_SUBTYPE_CTS:
+		case IEEE80211_FC0_SUBTYPE_ACK:
+			return sizeof(struct ieee80211_frame_ack);
+			break;
+		default:
+			return sizeof(struct ieee80211_frame_min);
+			break;
+		}
+	} else
+		return ieee80211_hdrsize(data);
+}
+
+/*
+ * Template for an in-kernel authenticator.  Authenticators
+ * register with the protocol code and are typically loaded
+ * as separate modules as needed.
+ */
+struct ieee80211_authenticator {
+	const char *ia_name;		/* printable name */
+	int (*ia_attach)(struct ieee80211vap *);
+	void (*ia_detach)(struct ieee80211vap *);
+	void (*ia_node_join)(struct ieee80211_node *);
+	void (*ia_node_leave)(struct ieee80211_node *);
+};
+void ieee80211_authenticator_register(int, const struct ieee80211_authenticator *);
+void ieee80211_authenticator_unregister(int);
+const struct ieee80211_authenticator *ieee80211_authenticator_get(int);
+
+struct eapolcom;
+/*
+ * Template for an in-kernel authenticator backend.  Backends
+ * register with the protocol code and are typically loaded
+ * as separate modules as needed.
+ */
+struct ieee80211_authenticator_backend {
+	const char *iab_name;		/* printable name */
+	int (*iab_attach)(struct eapolcom *);
+	void (*iab_detach)(struct eapolcom *);
+};
+void ieee80211_authenticator_backend_register(
+	const struct ieee80211_authenticator_backend *);
+void ieee80211_authenticator_backend_unregister(
+	const struct ieee80211_authenticator_backend *);
+const struct ieee80211_authenticator_backend *
+	ieee80211_authenticator_backend_get(const char *);
+
+/*
+ * Template for an MAC ACL policy module.  Such modules
+ * register with the protocol code and are passed the sender's
+ * address of each received frame for validation.
+ */
+struct ieee80211_aclator {
+	const char *iac_name;		/* printable name */
+	int (*iac_attach)(struct ieee80211vap *);
+	void (*iac_detach)(struct ieee80211vap *);
+	int (*iac_check)(struct ieee80211vap *,
+		const u_int8_t mac[IEEE80211_ADDR_LEN]);
+	int (*iac_add)(struct ieee80211vap *,
+		const u_int8_t mac[IEEE80211_ADDR_LEN]);
+	int (*iac_remove)(struct ieee80211vap *,
+		const u_int8_t mac[IEEE80211_ADDR_LEN]);
+	int (*iac_flush)(struct ieee80211vap *);
+	int (*iac_setpolicy)(struct ieee80211vap *, int);
+	int (*iac_getpolicy)(struct ieee80211vap *);
+};
+void ieee80211_aclator_register(const struct ieee80211_aclator *);
+void ieee80211_aclator_unregister(const struct ieee80211_aclator *);
+const struct ieee80211_aclator *ieee80211_aclator_get(const char *name);
+
+/* flags for ieee80211_fix_rate() */
+#define	IEEE80211_F_DOSORT	0x00000001	/* sort rate list */
+#define	IEEE80211_F_DOFRATE	0x00000002	/* use fixed rate */
+#define	IEEE80211_F_DONEGO	0x00000004	/* calc negotiated rate */
+#define	IEEE80211_F_DODEL	0x00000008	/* delete ignore rate */
+int	ieee80211_fix_rate(struct ieee80211_node *, int);
+
+struct wmeParams {
+	u_int8_t wmep_acm;		/* ACM parameter */
+	u_int8_t wmep_aifsn;		/* AIFSN parameters */
+	u_int8_t wmep_logcwmin;		/* cwmin in exponential form */
+	u_int8_t wmep_logcwmax;		/* cwmax in exponential form */
+	u_int16_t wmep_txopLimit;	/* txopLimit */
+	u_int8_t wmep_noackPolicy;	/* No-Ack Policy: 0=ack, 1=no-ack */
+};
+
+#define IEEE80211_EXPONENT_TO_VALUE(_exp) (1 << (u_int32_t)(_exp)) - 1
+#define IEEE80211_TXOP_TO_US(_txop)	(u_int32_t)(_txop) << 5
+#define IEEE80211_US_TO_TXOP(_us)	(u_int16_t)((u_int32_t)(_us)) >> 5
+
+struct chanAccParams{
+	/* XXX: is there any reason to have multiple instances of cap_info_count??? */
+	u_int8_t cap_info_count;		 	/* ver. of the current param set */
+	struct wmeParams cap_wmeParams[WME_NUM_AC];	/* WME params for each access class */
+};
+
+struct ieee80211_wme_state {
+	u_int32_t wme_flags;
+#define	WME_F_AGGRMODE	0x00000001	/* STATUS: WME aggressive mode */
+
+	u_int wme_hipri_traffic;		/* VI/VO frames in beacon interval */
+	u_int wme_hipri_switch_thresh;		/* aggressive mode switch threshold */
+	u_int wme_hipri_switch_hysteresis;	/* aggressive mode switch hysteresis */
+
+	struct chanAccParams wme_wmeChanParams;	/* configured WME parameters applied to itself*/
+	struct chanAccParams wme_wmeBssChanParams; /* configured WME parameters broadcasted to STAs*/
+	struct chanAccParams wme_chanParams;	/* channel parameters applied to itself*/
+	struct chanAccParams wme_bssChanParams;	/* channel parameters broadcasted to STAs*/
+	u_int8_t wme_nonAggressiveMode;   	/* don't use aggressive params and use WME params */
+
+	/* update hardware tx params after wme state change */
+	int (*wme_update)(struct ieee80211com *);
+};
+
+void ieee80211_wme_initparams(struct ieee80211vap *);
+void ieee80211_wme_initparams_locked(struct ieee80211vap *);
+void ieee80211_wme_updateparams(struct ieee80211vap *);
+void ieee80211_wme_updateparams_locked(struct ieee80211vap *);
+
+int ieee80211_open(struct net_device *);
+int ieee80211_init(struct net_device *, int);
+void ieee80211_start_running(struct ieee80211com *);
+int ieee80211_stop(struct net_device *);
+void ieee80211_stop_running(struct ieee80211com *);
+void ieee80211_beacon_miss(struct ieee80211com *);
+#ifdef ATH_SUPERG_DYNTURBO
+void ieee80211_dturbo_switch(struct ieee80211com *, int);
+#endif
+int ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int);
+void ieee80211_print_essid(const u_int8_t *, int);
+#ifdef IEEE80211_DEBUG
+void ieee80211_dump_pkt(struct ieee80211com *, const u_int8_t *, int, int, int);
+#else
+#define ieee80211_dump_pkt(...)
+#endif
+struct sk_buff *ieee80211_getcfframe(struct ieee80211vap *, int);
+
+/*
+ * Beacon frames constructed by ieee80211_beacon_alloc
+ * have the following structure filled in so drivers
+ * can update the frame later w/ minimal overhead.
+ */
+struct ieee80211_beacon_offsets {
+	__le16 *bo_caps;		/* capabilities */
+	u_int8_t *bo_tim;		/* start of atim/dtim */
+	u_int8_t *bo_wme;		/* start of WME parameters */
+	u_int8_t *bo_tim_trailer;	/* start of fixed-size tim trailer */
+	u_int16_t bo_tim_len;		/* atim/dtim length in bytes */
+	u_int16_t bo_tim_trailerlen;	/* trailer length in bytes */
+	u_int8_t *bo_chanswitch;		/* where channel switch IE will go */
+	u_int8_t *bo_ath_caps;		/* where ath caps is */
+	u_int8_t *bo_xr;			/* start of xr element */
+	u_int8_t *bo_erp;		/* start of ERP element */
+	u_int8_t *bo_appie_buf;		/* start of APP IE buf */
+	u_int16_t bo_appie_buf_len;	/* APP IE buf length in bytes */
+	u_int16_t bo_chanswitch_trailerlen;
+};
+struct sk_buff *ieee80211_beacon_alloc(struct ieee80211_node *,
+	struct ieee80211_beacon_offsets *);
+int ieee80211_beacon_update(struct ieee80211_node *,
+	struct ieee80211_beacon_offsets *, struct sk_buff *, int);
+
+/* XXX exposed due to of beacon code botch */
+u_int8_t *ieee80211_add_rates(u_int8_t *, const struct ieee80211_rateset *);
+u_int8_t *ieee80211_add_xrates(u_int8_t *, const struct ieee80211_rateset *);
+u_int8_t *ieee80211_add_wpa(u_int8_t *, struct ieee80211vap *);
+u_int8_t *ieee80211_add_erp(u_int8_t *, struct ieee80211com *);
+u_int8_t *ieee80211_add_athAdvCap(u_int8_t *, u_int8_t, u_int16_t);
+u_int8_t *ieee80211_add_xr_param(u_int8_t *, struct ieee80211vap *);
+u_int8_t *ieee80211_add_xr_param(u_int8_t *, struct ieee80211vap *);
+u_int8_t *ieee80211_add_wme_param(u_int8_t *, struct ieee80211_wme_state *, int);
+u_int8_t *ieee80211_add_country(u_int8_t *, struct ieee80211com *);
+u_int8_t *ieee80211_add_pwrcnstr(u_int8_t *frm, struct ieee80211com *ic);
+u_int8_t *ieee80211_add_athAdvCap(u_int8_t *, u_int8_t, u_int16_t);
+
+/*
+ * Notification methods called from the 802.11 state machine.
+ * Note that while these are defined here, their implementation
+ * is OS-specific.
+ */
+void ieee80211_notify_node_join(struct ieee80211_node *, int);
+void ieee80211_notify_node_leave(struct ieee80211_node *);
+void ieee80211_notify_scan_done(struct ieee80211vap *);
+void ieee80211_notify_sta_stats(struct ieee80211_node *ni);
+
+#endif /* _NET80211_IEEE80211_PROTO_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_radiotap.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_radiotap.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_radiotap.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_radiotap.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,258 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $NetBSD: ieee80211_radiotap.h,v 1.17 2007/03/26 04:32:14 dyoung Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 David Young.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_radiotap.h 2220 2007-03-26 11:56:18Z scottr $
+ */
+#ifndef _NET_IF_IEEE80211RADIOTAP_H_
+#define _NET_IF_IEEE80211RADIOTAP_H_
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+#if defined(__KERNEL__) || defined(_KERNEL)
+#ifndef DLT_IEEE802_11_RADIO
+#define	DLT_IEEE802_11_RADIO	127	/* 802.11 plus WLAN header */
+#endif
+#endif /* defined(__KERNEL__) || defined(_KERNEL) */
+
+/* The radio capture header precedes the 802.11 header. */
+struct ieee80211_radiotap_header {
+	u_int8_t it_version;		/* Version 0. Only increases
+					 * for drastic changes,
+					 * introduction of compatible
+					 * new fields does not count.
+					 */
+	u_int8_t it_pad;
+	__le16 it_len;			/* length of the whole
+					 * header in bytes, including
+					 * it_version, it_pad,
+					 * it_len, and data fields.
+					 */
+	__le32 it_present;		/* A bitmap telling which
+					 * fields are present. Set bit 31
+					 * (0x80000000) to extend the
+					 * bitmap by another 32 bits.
+					 * Additional extensions are made
+					 * by setting bit 31.
+					 */
+} __attribute__((__packed__));
+
+/* Name                                 Data type       Units
+ * ----                                 ---------       -----
+ *
+ * IEEE80211_RADIOTAP_TSFT              u_int64_t       microseconds
+ *
+ *      Value in microseconds of the MAC's 64-bit 802.11 Time
+ *      Synchronization Function timer when the first bit of the
+ *      MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL           2 x u_int16_t   MHz, bitmap
+ *
+ *      Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS              u_int16_t       see below
+ *
+ *      For frequency-hopping radios, the hop set (first byte)
+ *      and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE              u_int8_t        500kb/s
+ *
+ *      Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF signal power at the antenna, decibel difference from
+ *      one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF noise power at the antenna, decibel difference from one
+ *      milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u_int8_t        decibel (dB)
+ *
+ *      RF signal power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u_int8_t        decibel (dB)
+ *
+ *      RF noise power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_BARKER_CODE_LOCK  u_int16_t       unitless
+ *
+ *      Quality of Barker code lock. Unitless. Monotonically
+ *      nondecreasing with "better" lock strength. Called "Signal
+ *      Quality" in datasheets.  (Is there a standard way to measure
+ *      this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    u_int16_t       unitless
+ *
+ *      Transmit power expressed as unitless distance from max
+ *      power set at factory calibration.  0 is max power.
+ *      Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u_int16_t       decibels (dB)
+ *
+ *      Transmit power expressed as decibel distance from max power
+ *      set at factory calibration.  0 is max power.  Monotonically
+ *      nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      Transmit power expressed as dBm (decibels from a 1 milliwatt
+ *      reference). This is the absolute power level measured at
+ *      the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS             u_int8_t        bitmap
+ *
+ *      Properties of transmitted and received frames. See flags
+ *      defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA           u_int8_t        antenna index
+ *
+ *      Unitless indication of the Rx/Tx antenna for this packet.
+ *      The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_RX_FLAGS          u_int16_t       bitmap
+ *
+ *     Properties of received frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_TX_FLAGS          u_int16_t       bitmap
+ *
+ *     Properties of transmitted frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_RTS_RETRIES       u_int8_t        data
+ *
+ *     Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES      u_int8_t        data
+ *
+ *     Number of unicast retries a transmitted frame used.
+ */
+enum ieee80211_radiotap_type {
+	IEEE80211_RADIOTAP_TSFT = 0,
+	IEEE80211_RADIOTAP_FLAGS = 1,
+	IEEE80211_RADIOTAP_RATE = 2,
+	IEEE80211_RADIOTAP_CHANNEL = 3,
+	IEEE80211_RADIOTAP_FHSS = 4,
+	IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+	IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+	IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+	IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+	IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+	IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+	IEEE80211_RADIOTAP_ANTENNA = 11,
+	IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+	IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+	IEEE80211_RADIOTAP_RX_FLAGS = 14,
+	IEEE80211_RADIOTAP_TX_FLAGS = 15,
+	IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+	IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+	IEEE80211_RADIOTAP_EXT = 31,
+};
+
+#ifndef _KERNEL
+/* Channel flags. */
+#define IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
+#define IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
+#define IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
+#define	IEEE80211_CHAN_2GHZ	0x0080	/* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
+#define IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
+#define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
+#define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
+
+/* Useful combinations of channel characteristics, borrowed from Ethereal */
+#define IEEE80211_CHAN_A \
+	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
+#define IEEE80211_CHAN_B \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
+#define IEEE80211_CHAN_G \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
+#define IEEE80211_CHAN_TA \
+	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
+#define IEEE80211_CHAN_TG \
+	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN  | IEEE80211_CHAN_TURBO)
+
+#endif /* !_KERNEL */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
+						 * during CFP
+						 */
+#define	IEEE80211_RADIOTAP_F_SHORTPRE	0x02	/* sent/received
+						 * with short
+						 * preamble
+						 */
+#define	IEEE80211_RADIOTAP_F_WEP	0x04	/* sent/received
+						 * with WEP encryption
+						 */
+#define	IEEE80211_RADIOTAP_F_FRAG	0x08	/* sent/received
+						 * with fragmentation
+						 */
+#define	IEEE80211_RADIOTAP_F_FCS	0x10	/* frame includes FCS */
+#define	IEEE80211_RADIOTAP_F_DATAPAD	0x20	/* frame has padding between
+						 * 802.11 header and payload
+						 * (to 32-bit boundary)
+						 */
+#define	IEEE80211_RADIOTAP_F_BADFCS	0x40	/* does not pass FCS check */
+
+/* For IEEE80211_RADIOTAP_RX_FLAGS */
+#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001  /* Frame failed CRC check.
+						*
+						* Deprecated: use the flag
+						* IEEE80211_RADIOTAP_F_FCS in
+						* the IEEE80211_RADIOTAP_FLAGS
+						* field, instead.
+						*/
+
+/* For IEEE80211_RADIOTAP_TX_FLAGS */
+#define IEEE80211_RADIOTAP_F_TX_FAIL   0x0001  /* failed due to excessive
+						* retries
+						*/
+#define IEEE80211_RADIOTAP_F_TX_CTS    0x0002  /* used cts 'protection' */
+#define IEEE80211_RADIOTAP_F_TX_RTS    0x0004  /* used rts/cts handshake */
+#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_rate.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_rate.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_rate.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_rate.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+	without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: if_athrate.h 1667 2006-07-04 10:23:35Z kelmo $
+ */
+#ifndef _ATH_RATECTRL_H_
+#define _ATH_RATECTRL_H_
+
+/*
+ * Interface definitions for transmit rate control modules for the
+ * Atheros driver.
+ *
+ * A rate control module is responsible for choosing the transmit rate
+ * for each data frame.  Management+control frames are always sent at
+ * a fixed rate.
+ *
+ * An instance of the rate control module is attached to each device
+ * at attach time and detached when the device is destroyed.  The module
+ * may associate data with each device and each node (station).  Both
+ * sets of storage are opaque except for the size of the per-node storage
+ * which must be provided when the module is attached.
+ *
+ * The rate control module is notified for each state transition and
+ * station association/reassociation.  Otherwise it is queried for a
+ * rate for each outgoing frame and provided status from each transmitted
+ * frame.  Any ancillary processing is the responsibility of the module
+ * (e.g. if periodic processing is required then the module should setup
+ * its own timer).
+ *
+ * In addition to the transmit rate for each frame, the module must also
+ * indicate the number of attempts to make at the specified rate.  If this
+ * number is != ATH_TXMAXTRY, an additional callback is made to request
+ * 3 additional rate/retry pairs.
+ */
+
+enum {
+	IEEE80211_RATE_AMRR,
+	IEEE80211_RATE_MINSTREL,
+	IEEE80211_RATE_ONOE,
+	IEEE80211_RATE_SAMPLE,
+	IEEE80211_RATE_MAX
+};
+
+struct ath_softc;
+struct ath_node;
+struct ath_buf;
+struct ieee80211vap;
+
+/* Multi-rare retry: 3 additional rate/retry pairs */
+struct ieee80211_mrr {
+	int rate1;
+	int retries1;
+	int rate2;
+	int retries2;
+	int rate3;
+	int retries3;
+	int privflags;
+};
+
+struct ieee80211_rate_ops {
+	int ratectl_id;
+
+	/* Attach/detach a rate control module */
+	struct ath_ratectrl *(*attach)(struct ath_softc *sc);
+	void (*detach)(struct ath_ratectrl *arc);
+
+	/* Register proc entries with a VAP */
+	void (*dynamic_proc_register)(struct ieee80211vap *vap);
+
+	/* *** State storage handling *** */
+
+	/* Initialize per-node state already allocated for the specified
+	 * node; this space can be assumed initialized to zero */
+	void (*node_init)(struct ath_softc *sc, struct ath_node *an);
+
+	/* Cleanup any per-node state prior to the node being reclaimed */
+	void (*node_cleanup)(struct ath_softc *sc, struct ath_node *an);
+
+	/* Update rate control state on station associate/reassociate 
+	 * (when operating as an ap or for nodes discovered when operating
+	 * in ibss mode) */
+	void (*newassoc)(struct ath_softc *sc, struct ath_node *an,
+			 int isnew);
+
+	/* Update/reset rate control state for 802.11 state transitions.
+	 * Important mostly as the analog to newassoc when operating
+	 * in station mode */
+	void (*newstate)(struct ieee80211vap *vap,
+			 enum ieee80211_state state);
+
+	/* *** Transmit handling *** */
+
+	/* Return the transmit info for a data packet.  If multi-rate state
+	 * is to be setup then try0 should contain a value other than ATH_TXMAXTRY
+	 * and setupxtxdesc will be called after deciding if the frame
+	 * can be transmitted with multi-rate retry. */
+	void (*findrate)(struct ath_softc *sc, struct ath_node *an,
+			 int shortPreamble, size_t frameLen,
+			 u_int8_t *rix, unsigned int *try0, u_int8_t *txrate);
+
+	/* Return 3 more rates to try and corresponding number of retries.
+	 * The rate index returned by findrate is passed back in. */
+	void (*get_mrr)(struct ath_softc *sc, struct ath_node *an,
+			int shortPreamble, size_t frame_size, u_int8_t rix,
+			struct ieee80211_mrr *mrr);
+
+	/* Update rate control state for a packet associated with the
+	 * supplied transmit descriptor.  The routine is invoked both
+	 * for packets that were successfully sent and for those that
+	 * failed (consult the descriptor for details). */
+	void (*tx_complete)(struct ath_softc *sc, struct ath_node *an,
+			    const struct ath_buf *bf);
+};
+
+struct ath_ratectrl {
+	struct ieee80211_rate_ops *ops;
+	size_t arc_space;	/* space required for per-node state */
+	size_t arc_vap_space;	/* space required for per-vap state */
+};
+
+int ieee80211_rate_register(struct ieee80211_rate_ops *ops);
+void ieee80211_rate_unregister(struct ieee80211_rate_ops *ops);
+
+struct ath_ratectrl *ieee80211_rate_attach(struct ath_softc *sc, const char *name);
+void ieee80211_rate_detach(struct ath_ratectrl *);
+#endif /* _ATH_RATECTRL_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_scan.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_scan.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_scan.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_scan.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,225 @@
+/*-
+ * Copyright (c) 2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_scan.h 2513 2007-06-25 03:48:07Z mentor $
+ */
+#ifndef _NET80211_IEEE80211_SCAN_H_
+#define _NET80211_IEEE80211_SCAN_H_
+
+#define	IEEE80211_SCAN_MAX	IEEE80211_CHAN_MAX
+
+struct ieee80211_scanner;
+struct ieee80211_scan_entry;
+
+struct ieee80211_scan_ssid {
+	int len;				/* length in bytes */
+	u_int8_t ssid[IEEE80211_NWID_LEN];	/* ssid contents */
+};
+#define	IEEE80211_SCAN_MAX_SSID	1
+
+struct ieee80211_scan_state {
+	struct ieee80211vap *ss_vap;
+	const struct ieee80211_scanner *ss_ops;	/* policy hookup, see below */
+	void *ss_priv;				/* scanner private state */
+	u_int16_t ss_flags;
+#define	IEEE80211_SCAN_NOPICK	0x0001		/* scan only, no selection */
+#define	IEEE80211_SCAN_ACTIVE	0x0002		/* active scan (probe req) */
+#define	IEEE80211_SCAN_PICK1ST	0x0004		/* ``hey sailor'' mode */
+#define	IEEE80211_SCAN_BGSCAN	0x0008		/* bg scan, exit ps at end */
+#define	IEEE80211_SCAN_ONCE	0x0010		/* do one complete pass */
+#define	IEEE80211_SCAN_GOTPICK	0x1000		/* got candidate, can stop */
+
+	u_int8_t	ss_nssid;			/* # SSIDs to probe/match */
+	struct ieee80211_scan_ssid ss_ssid[IEEE80211_SCAN_MAX_SSID];
+						/* SSIDs to probe/match */
+						/* ordered channel set */
+	struct ieee80211_channel *ss_chans[IEEE80211_SCAN_MAX];
+	u_int16_t ss_next;			/* ix of next chan to scan */
+	u_int16_t ss_last;			/* ix + 1 of last chan to scan */
+	unsigned long ss_mindwell;		/* min dwell on channel */
+	unsigned long ss_maxdwell;		/* max dwell on channel */
+	u_int ss_duration;			/* used for calling ieee80211_start_scan() */
+};
+
+/*
+ * The upper 16 bits of the flags word is used to communicate
+ * information to the scanning code that is NOT recorded in
+ * ss_flags.  It might be better to split this stuff out into
+ * a separate variable to avoid confusion.
+ */
+#define	IEEE80211_SCAN_FLUSH	0x10000		/* flush candidate table */
+#define	IEEE80211_SCAN_NOSSID	0x20000		/* don't update ssid list */
+#define	IEEE80211_SCAN_USECACHE	0x40000		/* Must use a result from the cache */
+#define	IEEE80211_SCAN_KEEPMODE	0x80000		/* Must keep the same wireless mode (11a, 11g, or 11at, etc) */
+
+struct ieee80211com;
+void ieee80211_scan_attach(struct ieee80211com *);
+void ieee80211_scan_detach(struct ieee80211com *);
+void ieee80211_scan_vattach(struct ieee80211vap *);
+void ieee80211_scan_vdetach(struct ieee80211vap *);
+
+void ieee80211_scan_dump_channels(const struct ieee80211_scan_state *);
+
+#define	IEEE80211_SCAN_FOREVER	0x7fffffff
+int ieee80211_start_scan(struct ieee80211vap *, int, u_int, u_int,
+	const struct ieee80211_scan_ssid ssids[]);
+int ieee80211_check_scan(struct ieee80211vap *, int, u_int, u_int,
+	const struct ieee80211_scan_ssid ssids[],
+	int (*action)(struct ieee80211vap *, const struct ieee80211_scan_entry *));
+int ieee80211_bg_scan(struct ieee80211vap *);
+void ieee80211_cancel_scan(struct ieee80211vap *);
+
+int ieee80211_scan_dfs_action(struct ieee80211vap *, const struct ieee80211_scan_entry *);
+
+struct ieee80211_scanparams;
+void ieee80211_add_scan(struct ieee80211vap *, const struct ieee80211_scanparams *,
+	const struct ieee80211_frame *, int, int, u_int64_t);
+void ieee80211_scan_timeout(struct ieee80211com *);
+
+void ieee80211_scan_assoc_success(struct ieee80211com *,
+	const u_int8_t mac[IEEE80211_ADDR_LEN]);
+enum {
+	IEEE80211_SCAN_FAIL_TIMEOUT	= 1,	/* no response to mgmt frame */
+	IEEE80211_SCAN_FAIL_STATUS	= 2	/* negative response to " " */
+};
+void ieee80211_scan_assoc_fail(struct ieee80211com *,
+	const u_int8_t mac[IEEE80211_ADDR_LEN], int);
+void ieee80211_scan_flush(struct ieee80211com *);
+
+struct ieee80211_scan_entry;
+typedef int ieee80211_scan_iter_func(void *, const struct ieee80211_scan_entry *);
+int ieee80211_scan_iterate(struct ieee80211com *, ieee80211_scan_iter_func *, void *);
+
+/*
+ * Parameters supplied when adding/updating an entry in a
+ * scan cache.  Pointer variables should be set to NULL
+ * if no data is available.  Pointer references can be to
+ * local data; any information that is saved will be copied.
+ * All multi-byte values must be in host byte order.
+ */
+struct ieee80211_scanparams {
+	u_int16_t capinfo;	/* 802.11 capabilities */
+	u_int16_t fhdwell;	/* FHSS dwell interval */
+	u_int8_t chan;		/* */
+	u_int8_t bchan;
+	u_int8_t fhindex;
+	u_int8_t erp;
+	u_int16_t bintval;
+	u_int8_t timoff;
+	u_int8_t *tim;
+	u_int8_t *tstamp;
+	u_int8_t *country;
+	u_int8_t *ssid;
+	u_int8_t *rates;
+	u_int8_t *xrates;
+	u_int8_t *csa;
+	u_int8_t *wpa;
+	u_int8_t *rsn;
+	u_int8_t *wme;
+	u_int8_t *ath;
+};
+
+/*
+ * Scan cache entry format used when exporting data from a policy
+ * module; this data may be represented some other way internally.
+ */
+struct ieee80211_scan_entry {
+	u_int8_t se_macaddr[IEEE80211_ADDR_LEN];
+	u_int8_t se_bssid[IEEE80211_ADDR_LEN];
+	u_int8_t se_ssid[2 + IEEE80211_NWID_LEN];
+	u_int8_t se_rates[2 + IEEE80211_RATE_MAXSIZE];
+	u_int8_t se_xrates[2 + IEEE80211_RATE_MAXSIZE];
+	u_int64_t se_rtsf;		/* recv timestamp */
+	union {
+		u_int8_t data[8];
+		__le64 tsf;
+	} se_tstamp;			/* from last rcv'd beacon */
+	u_int16_t se_intval;		/* beacon interval (host byte order) */
+	u_int16_t se_capinfo;		/* capabilities (host byte order) */
+	struct ieee80211_channel *se_chan;/* channel where sta found */
+	u_int16_t se_timoff;		/* byte offset to TIM ie */
+	u_int16_t se_fhdwell;		/* FH only (host byte order) */
+	u_int8_t se_fhindex;		/* FH only */
+	u_int8_t se_erp;			/* ERP from beacon/probe resp */
+	int8_t se_rssi;			/* avg'd recv ssi */
+	u_int8_t se_dtimperiod;		/* DTIM period */
+	u_int8_t *se_wpa_ie;		/* captured WPA ie */
+	u_int8_t *se_rsn_ie;		/* captured RSN ie */
+	u_int8_t *se_wme_ie;		/* captured WME ie */
+	u_int8_t *se_ath_ie;		/* captured Atheros ie */
+	u_int se_age;			/* age of entry (0 on create) */
+};
+
+/*
+ * Template for an in-kernel scan policy module.
+ * Modules register with the scanning code and are
+ * typically loaded as needed.
+ */
+struct ieee80211_scanner {
+	const char *scan_name;		/* printable name */
+	int (*scan_attach)(struct ieee80211_scan_state *);
+	int (*scan_detach)(struct ieee80211_scan_state *);
+	int (*scan_start)(struct ieee80211_scan_state *, struct ieee80211vap *);
+	int (*scan_restart)(struct ieee80211_scan_state *, struct ieee80211vap *);
+	int (*scan_cancel)(struct ieee80211_scan_state *, struct ieee80211vap *);
+	int (*scan_end)(struct ieee80211_scan_state *, struct ieee80211vap *,
+		int (*action)(struct ieee80211vap *, const struct ieee80211_scan_entry *),
+		u_int32_t);
+	int (*scan_flush)(struct ieee80211_scan_state *);
+	/* add an entry to the cache */
+	int (*scan_add)(struct ieee80211_scan_state *,
+		const struct ieee80211_scanparams *,
+		const struct ieee80211_frame *, int, int, u_int64_t);
+	/* age and/or purge entries in the cache */
+	void (*scan_age)(struct ieee80211_scan_state *);
+	/* note that association failed for an entry */
+	void (*scan_assoc_fail)(struct ieee80211_scan_state *,
+		const u_int8_t macaddr[IEEE80211_ADDR_LEN], int);
+	/* note that association succeed for an entry */
+	void (*scan_assoc_success)(struct ieee80211_scan_state *,
+		const u_int8_t macaddr[IEEE80211_ADDR_LEN]);
+	/* iterate over entries in the scan cache */
+	int (*scan_iterate)(struct ieee80211_scan_state *,
+		ieee80211_scan_iter_func *, void *);
+	/* default action to take when found scan match */
+	int (*scan_default)(struct ieee80211vap *,
+		const struct ieee80211_scan_entry *);
+};
+const struct ieee80211_scanner *ieee80211_scanner_get(enum ieee80211_opmode,
+	int);
+void ieee80211_scanner_register(enum ieee80211_opmode,
+	const struct ieee80211_scanner *);
+void ieee80211_scanner_unregister(enum ieee80211_opmode,
+	const struct ieee80211_scanner *);
+void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
+void ieee80211_scan_add_channels(struct ieee80211com *ic,
+	struct ieee80211_scan_state *ss,
+	enum ieee80211_phymode mode);
+#endif /* _NET80211_IEEE80211_SCAN_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_skb.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_skb.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_skb.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_skb.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,204 @@
+/*-
+ * Copyright (c) 2007 Michael Taylor, Apprion
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_skb.h 2647 2007-08-09 08:43:58Z mtaylor $
+ */
+#ifndef _NET80211_IEEE80211_SKB_H_
+#define _NET80211_IEEE80211_SKB_H_
+
+/*******************************************************************************
+ * Globals
+ ******************************************************************************/
+
+#ifdef IEEE80211_DEBUG_REFCNT
+
+/* Count of currently tracked skbs */
+extern atomic_t skb_total_counter;
+/* Count of currently tracked skbs' references */
+extern atomic_t skb_refs_counter;
+
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+/*******************************************************************************
+ * Public API
+ ******************************************************************************/
+
+/* ieee80211_dev_kfree_skb will release one reference from SKB.
+ * If SKB refcount is going to zero:
+ *  - Free the node reference and set it to null.
+ *  - Break the linked list, clearing next skb's prev pointer if possible. */
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_dev_kfree_skb(_pskb) \
+	ieee80211_dev_kfree_skb_debug(_pskb, __func__, __LINE__)
+void ieee80211_dev_kfree_skb_debug(struct sk_buff** pskb, const char* func, int line);
+#else
+void ieee80211_dev_kfree_skb(struct sk_buff** pskb);
+#endif
+
+static inline void ieee80211_skb_copy_noderef(struct sk_buff *src, 
+		struct sk_buff *dst)
+{
+	if (SKB_CB(src)->ni != NULL)
+		SKB_CB(dst)->ni = ieee80211_ref_node(SKB_CB(src)->ni);
+}
+
+/*
+ * ieee80211_dev_kfree_skb_list will invoke ieee80211_dev_kfree_skb on each node in
+ * a list of skbs, starting with the first.
+*/
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_dev_kfree_skb_list(_pskb) \
+	ieee80211_dev_kfree_skb_list_debug(_pskb, __func__, __LINE__)
+void ieee80211_dev_kfree_skb_list_debug(struct sk_buff** pskb, const char* func, int line);
+#else
+void ieee80211_dev_kfree_skb_list(struct sk_buff** pskb);
+#endif
+
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_dev_alloc_skb(_size) \
+	ieee80211_dev_alloc_skb_debug(_size, __func__, __LINE__)
+struct sk_buff* ieee80211_dev_alloc_skb_debug(int size, const char* func, int line);
+#else
+struct sk_buff* ieee80211_dev_alloc_skb(int size);
+#endif
+
+#ifdef IEEE80211_DEBUG_REFCNT
+#define ieee80211_skb_track(_skb) \
+	ieee80211_skb_track_debug(_skb, __func__, __LINE__)
+#define ieee80211_skb_untrack(_skb) \
+	ieee80211_skb_untrack_debug(_skb, __func__, __LINE__)
+void ieee80211_skb_track_debug(struct sk_buff *skb, 
+					       const char* func, int line);
+void ieee80211_skb_untrack_debug(struct sk_buff *skb, 
+					       const char* func, int line);
+#else
+void ieee80211_skb_track(struct sk_buff *skb);
+void ieee80211_skb_untrack(struct sk_buff *skb);
+#endif
+
+#ifdef IEEE80211_DEBUG_REFCNT
+int ieee80211_skb_counter(void);
+int ieee80211_skb_references(void);
+#else
+#define ieee80211_skb_counter() (0)
+#define ieee80211_skb_references() (0)
+#endif
+
+/*******************************************************************************
+ * skbuff leak/refcount debugging Replacement Functions
+ ******************************************************************************/
+
+#ifdef IEEE80211_DEBUG_REFCNT
+
+int  vlan_hwaccel_receive_skb_debug(struct sk_buff *skb, 
+				    struct vlan_group *grp, unsigned short vlan_tag, 
+				    const char* func, int line);
+int netif_receive_skb_debug(struct sk_buff *skb, const char* func, int line);
+struct sk_buff * alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
+				 const char *func, int line);
+struct sk_buff * dev_alloc_skb_debug(unsigned int length,
+				     const char *func, int line);
+struct sk_buff * skb_clone_debug(struct sk_buff *skb, gfp_t pri, 
+				 const char *func, int line);
+struct sk_buff * skb_copy_debug(struct sk_buff *skb, gfp_t pri, 
+				const char *func, int line);
+struct sk_buff * skb_get_debug(struct sk_buff *skb, 
+			       const char *func, int line);
+struct sk_buff * skb_realloc_headroom_debug(struct sk_buff *skb, unsigned int headroom, 
+					    const char *func, int line);
+struct sk_buff * pskb_copy_debug(struct sk_buff *skb, gfp_t pri,
+				 const char *func, int line);
+int dev_queue_xmit_debug(struct sk_buff *skb,
+			 const char *func, int line);
+struct sk_buff * skb_share_check_debug(struct sk_buff *skb, gfp_t pri,
+				       const char *func, int line);
+void  kfree_skb_fast_debug(struct sk_buff *skb, 
+			   const char* func, int line);
+struct sk_buff *  skb_unshare_debug(struct sk_buff *skb, gfp_t pri,
+				    const char *func, int line);
+struct sk_buff * skb_copy_expand_debug(const struct sk_buff *skb, int newheadroom, 
+				       int newtailroom, gfp_t gfp_mask, 
+				       const char *func, int line);
+
+#undef alloc_skb
+#undef dev_alloc_skb
+#undef dev_kfree_skb
+#undef dev_kfree_skb_any
+#undef dev_kfree_skb_irq
+#undef dev_queue_xmit
+#undef kfree_skb
+#undef kfree_skb_fast
+#undef netif_receive_skb
+#undef pskb_copy
+#undef skb_clone
+#undef skb_copy
+#undef skb_copy_expand
+#undef skb_get
+#undef skb_realloc_headroom
+#undef skb_share_check
+#undef skb_unshare
+#undef vlan_hwaccel_receive_skb
+
+#define skb_unshare(_skb, _pri) \
+	skb_unshare_debug(_skb, _pri, __func__, __LINE__)
+#define skb_copy_expand(_skb, _newheadroom, _newtailroom, _gfp_mask) \
+	skb_copy_expand_debug(_skb, _newheadroom, _newtailroom, _gfp_mask, __func__, __LINE__)
+#define vlan_hwaccel_receive_skb(_skb, _grp, _tag) \
+	vlan_hwaccel_receive_skb_debug(_skb, _grp, _tag, __func__, __LINE__)
+#define netif_receive_skb(_skb) \
+	netif_receive_skb_debug(_skb, __func__, __LINE__)
+#define	alloc_skb(_length, _gfp_mask) \
+	alloc_skb_debug(_length, _gfp_mask, __func__, __LINE__)
+#define	dev_alloc_skb(_length) \
+	dev_alloc_skb_debug(_length, __func__, __LINE__)
+#define	dev_kfree_skb_irq(_skb) \
+	unref_skb(_skb, UNREF_USE_DEV_KFREE_SKB_IRQ, __func__, __LINE__)
+#define	dev_kfree_skb_any(_skb) \
+	unref_skb(_skb, UNREF_USE_DEV_KFREE_SKB_ANY, __func__, __LINE__)
+#define	dev_kfree_skb(_skb) \
+	unref_skb(_skb, UNREF_USE_DEV_KFREE_SKB, __func__, __LINE__)
+#define	kfree_skb(_skb) \
+	unref_skb(_skb, UNREF_USE_KFREE_SKB, __func__, __LINE__)
+#define skb_clone(_skb, _pri) \
+	skb_clone_debug(_skb, _pri, __func__, __LINE__)
+#define skb_share_check(_skb, _pri) \
+	skb_share_check_debug(_skb, _pri, __func__, __LINE__)
+#define kfree_skb_fast(_skb) \
+	kfree_skb_fast_debug(_skb, __func__, __LINE__)
+#define skb_realloc_headroom(_skb, _headroom) \
+	skb_realloc_headroom_debug(_skb, _headroom, __func__, __LINE__)
+#define pskb_copy(_skb, _pri) \
+	pskb_copy_debug(_skb, _pri, __func__, __LINE__)
+#define skb_get(_skb) \
+	skb_get_debug(_skb, __func__, __LINE__)
+#define skb_copy(_skb, _pri) \
+	skb_copy_debug(_skb, _pri, __func__, __LINE__)
+#define dev_queue_xmit(_skb) \
+	dev_queue_xmit_debug(_skb, __func__, __LINE__)
+#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+#endif /* _NET80211_IEEE80211_SKB_H_ */
+
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_var.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_var.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_var.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/ieee80211_var.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,784 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_var.h 3314 2008-01-30 23:50:16Z mtaylor $
+ */
+
+#ifndef _NET80211_IEEE80211_VAR_H_
+#define _NET80211_IEEE80211_VAR_H_
+
+/* Definitions for IEEE 802.11 drivers. */
+#include <net80211/ieee80211_linux.h>
+
+#include <sys/queue.h>
+
+#include <net80211/_ieee80211.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+#include <net80211/ieee80211_ioctl.h>		/* for ieee80211_stats */
+#include <net80211/ieee80211_power.h>
+#include <net80211/ieee80211_proto.h>
+#include <net80211/ieee80211_scan.h>
+
+/* NB: 
+ * - Atheros chips use 6 bits when power is specified in whole dBm units, with 
+ *   a value range from 0 to 63.
+ * - Atheros chips use 7 bits when power is specified in half dBm units, with 
+ *   a value range from 0 to 127.
+ */
+#define	IEEE80211_TXPOWER_MAX		127	/* .5 dBm units */
+#define	IEEE80211_TXPOWER_MIN		0	/* kill radio */
+
+#define	IEEE80211_DTIM_MAX		15	/* max DTIM period */
+#define	IEEE80211_DTIM_MIN		1	/* min DTIM period */
+#define	IEEE80211_DTIM_DEFAULT		1	/* default DTIM period */
+
+#define	IEEE80211_BINTVAL_MAX		1000	/* max beacon interval (TUs) */
+#define	IEEE80211_BINTVAL_MIN		25	/* min beacon interval (TUs) */
+#define	IEEE80211_BINTVAL_DEFAULT 	100	/* default beacon interval (TUs) */
+#define IEEE80211_BINTVAL_VALID(_bi) \
+	((IEEE80211_BINTVAL_MIN <= (_bi)) && \
+	 ((_bi) <= IEEE80211_BINTVAL_MAX))
+#define IEEE80211_BINTVAL_SANITISE(_bi) \
+	(IEEE80211_BINTVAL_VALID(_bi) ? \
+	 (_bi) : IEEE80211_BINTVAL_DEFAULT)
+
+#define IEEE80211_BMISSTHRESH_BMIN	2	/* min bmiss threshold (beacons) */
+/* Default beacon miss threshold is set to roundup from 850ms 
+ * This is halfway between the 10@100ms default from prior hardcoded setting for
+ * software beacon miss timers, and the 7@100ms default from prior hardcoded 
+ * timer value for hardware beacon miss timer.
+ * Based upon emperical evidence and practices of commercial vendors, I believe
+ * this should really be 2500ms by default. */
+#define IEEE80211_BMISSTHRESH_DEFAULT_MS 850
+
+#define IEEE80211_BMISSTHRESH_VALID(_bmt) \
+	(IEEE80211_BMISSTHRESH_BMIN <= (_bmt))
+#define IEEE80211_BMISSTHRESH_SANITISE(_bmt) \
+	((IEEE80211_BMISSTHRESH_BMIN > (_bmt)) ? \
+	 IEEE80211_BMISSTHRESH_BMIN : (_bmt))
+
+#define	IEEE80211_BGSCAN_INTVAL_MIN	15	/* min bg scan intvl (secs) */
+#define	IEEE80211_BGSCAN_INTVAL_DEFAULT	(5*60)	/* default bg scan intvl */
+
+#define	IEEE80211_BGSCAN_IDLE_MIN	100	/* min idle time (ms) */
+#define	IEEE80211_BGSCAN_IDLE_DEFAULT	250	/* default idle time (ms) */
+
+#define IEEE80211_COVERAGE_CLASS_MAX	31	/* max coverage class */
+#define IEEE80211_REGCLASSIDS_MAX	10	/* max regclass id list */
+
+#define	IEEE80211_PS_SLEEP	0x1		/* STA is in power saving mode */
+#define	IEEE80211_PS_MAX_QUEUE	50		/* maximum saved packets */
+
+#define	IEEE80211_XR_BEACON_FACTOR	3	/* factor between xr Beacon interval and normal beacon interval */
+#define	IEEE80211_XR_DEFAULT_RATE_INDEX	0
+#define	IEEE80211_XR_FRAG_THRESHOLD	540
+
+#define	IEEE80211_FIXED_RATE_NONE	-1
+
+#define DEV_NAME(_d) \
+	 ((NULL == _d || NULL == _d->name || 0 == strncmp(_d->name, "wifi%d", 6)) ? \
+	  "MadWifi" : \
+	  _d->name)
+#define VAP_DEV_NAME(_v) \
+	 ((NULL == _v) ? \
+	  "MadWifi" : \
+	  DEV_NAME(_v->iv_dev))
+#define SC_DEV_NAME(_sc) \
+	 ((NULL == _sc) ? \
+	  "MadWifi" : \
+	  DEV_NAME(_sc->sc_dev))
+#define VAP_IC_DEV_NAME(_v) \
+	 ((NULL == _v || NULL == _v->iv_ic) ? \
+	  "MadWifi" : \
+	  DEV_NAME(_v->iv_ic->ic_dev))
+
+#define	IEEE80211_MS_TO_TU(x)	(((x) * 1000) / 1024)
+#define	IEEE80211_TU_TO_MS(x)	(((x) * 1024) / 1000)
+#define	IEEE80211_TU_TO_JIFFIES(x) ((IEEE80211_TU_TO_MS(x) * HZ) / 1000)
+#define	IEEE80211_JIFFIES_TO_TU(x) IEEE80211_MS_TO_TU((x) * 1000 / HZ)
+
+#define	IEEE80211_APPIE_MAX	1024
+
+#define IEEE80211_PROTMODE_RSSITHR	15	/* default rssi threshold for protection mode trigger */
+#define IEEE80211_PROTMODE_TIMEOUT	30	/* timeout for keeping protection mode alive */
+
+#define IEEE80211_PWRCONSTRAINT_VAL(ic) \
+	(((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \
+	    (ic)->ic_bsschan->ic_maxregpower - (ic)->ic_curchanmaxpwr : 0)
+
+/* 802.11 control state is split into a common portion that maps
+ * 1-1 to a physical device and one or more "Virtual APs" (VAP)
+ * that are bound to an ieee80211com instance and share a single
+ * underlying device.  Each VAP has a corresponding OS device
+ * entity through which traffic flows and that applications use
+ * for issuing ioctls, etc.
+ */
+
+/* Data common to one or more virtual APs.  State shared by
+ * the underlying device and the net80211 layer is exposed here;
+ * e.g. device-specific callbacks.
+ */
+
+struct ieee80211com;
+struct ieee80211_proc_entry;
+struct vlan_group;
+struct eapolcom;
+struct ieee80211_aclator;
+
+struct ieee80211_nsparams {
+	enum ieee80211_state newstate;
+	int arg;
+	int result;
+};
+
+#define IW_MAX_SPY 8
+struct ieee80211_spy {
+	u_int8_t mac[IW_MAX_SPY * IEEE80211_ADDR_LEN];
+	u_int64_t ts_rssi[IW_MAX_SPY];		/* ts of rssi value from last read */
+	u_int8_t thr_low;			/* 1 byte rssi value, 0 = threshold is off */
+	u_int8_t thr_high;			/* 1 byte rssi value */
+	u_int8_t num;
+};
+
+struct ieee80211_app_ie {
+	u_int32_t		length;		/* buffer length */
+	struct ieee80211_ie    *ie;		/* buffer containing one or more IEs */
+};
+
+struct ieee80211vap {
+	struct net_device *iv_dev;			/* associated device */
+	struct net_device_stats	iv_devstats;		/* interface statistics */
+	struct ifmedia iv_media;			/* interface media config */
+	struct iw_statistics iv_iwstats;		/* wireless statistics block */
+	struct ctl_table_header	*iv_sysctl_header;
+	struct ctl_table *iv_sysctls;
+	struct proc_dir_entry *iv_proc;
+	struct ieee80211_proc_entry *iv_proc_entries;
+	struct vlan_group *iv_vlgrp;			/* vlan group state */
+
+	TAILQ_ENTRY(ieee80211vap) iv_next;		/* list of vap instances */
+	struct ieee80211com *iv_ic;			/* back ptr to common state */
+	u_int32_t iv_debug;				/* debug msg flags */
+	struct ieee80211_stats iv_stats;		/* statistics */
+
+	int iv_monitor_nods_only;			/* in monitor mode only nods traffic */
+	int iv_monitor_txf_len;				/* in monitor mode, truncate tx packets */
+	int iv_monitor_phy_errors;			/* in monitor mode, accept phy errors */
+	int iv_monitor_crc_errors;			/* in monitor mode, accept crc errors */
+
+	int (*iv_newstate)(struct ieee80211vap *, enum ieee80211_state, int);
+	u_int8_t iv_myaddr[IEEE80211_ADDR_LEN];
+	u_int32_t iv_flags;				/* state flags */
+	u_int32_t iv_flags_ext;				/* extension of state flags */
+	u_int32_t iv_caps;				/* capabilities */
+	u_int8_t iv_ath_cap;				/* Atheros adv. capabilities */
+	enum ieee80211_opmode iv_opmode;		/* operation mode */
+	enum ieee80211_state iv_state;			/* state machine state */
+	struct timer_list iv_mgtsend;			/* mgmt frame response timer */
+							/* inactivity timer settings */
+	int iv_inact_init;				/* setting for new station */
+	int iv_inact_auth;				/* auth but not assoc setting */
+	int iv_inact_run;				/* authorized setting */
+	int iv_inact_probe;				/* inactive probe time */
+
+	int iv_des_nssid;				/* # desired ssids */
+	struct ieee80211_scan_ssid iv_des_ssid[1];	/* desired ssid table */
+	u_int8_t iv_des_bssid[IEEE80211_ADDR_LEN];
+	struct ieee80211_channel *iv_des_chan;		/* desired channel */
+	u_int16_t iv_des_mode;				/* desired mode */
+	int iv_nicknamelen;				/* XXX junk */
+	u_int8_t iv_nickname[IEEE80211_NWID_LEN];
+	u_int iv_bgscanidle;				/* bg scan idle threshold */
+	u_int iv_bgscanintvl;				/* bg scan min interval */
+	u_int iv_scanvalid;				/* scan cache valid threshold */
+	struct ieee80211_roam iv_roam;			/* sta-mode roaming state */
+
+	u_int32_t iv_csa_jiffies;			/* last csa recv jiffies */
+	u_int8_t iv_csa_count;				/* last csa count */
+	struct ieee80211_channel *iv_csa_chan;		/* last csa channel */
+	u_int8_t iv_csa_mode;				/* last csa mode */
+	struct timer_list iv_csa_timer;			/* csa timer */
+	u_int32_t *iv_aid_bitmap;			/* association id map */
+	u_int16_t iv_max_aid;
+	u_int16_t iv_sta_assoc;				/* stations associated */
+	u_int16_t iv_ps_sta;				/* stations in power save */
+	u_int16_t iv_ps_pending;			/* PS STAs w/ pending frames */
+	u_int8_t *iv_tim_bitmap;			/* power-save stations w/ data*/
+	u_int16_t iv_tim_len;				/* ic_tim_bitmap size (bytes) */
+	u_int8_t iv_dtim_period;			/* DTIM period */
+	u_int8_t iv_dtim_count;				/* DTIM count from last bcn */
+							/* set/unset aid pwrsav state */
+	void (*iv_set_tim)(struct ieee80211_node *, int);
+	u_int8_t iv_uapsdinfo;				/* sta mode QoS Info flags */
+	struct ieee80211_node *iv_bss;			/* information for this node */
+
+	u_int8_t iv_bssid[IEEE80211_ADDR_LEN];
+
+	int iv_fixed_rate;				/* 802.11 rate or IEEE80211_FIXED_RATE_NONE */
+	u_int16_t iv_rtsthreshold;
+	u_int16_t iv_fragthreshold;
+	u_int16_t iv_txmin;				/* min tx retry count */
+	u_int16_t iv_txmax;				/* max tx retry count */
+	u_int16_t iv_txlifetime;			/* tx lifetime */
+	int iv_inact_timer;				/* inactivity timer wait */
+	void *iv_opt_ie;				/* user-specified IEs */
+	u_int16_t iv_opt_ie_len;			/* length of ni_opt_ie */
+	ieee80211_keyix_t iv_def_txkey;			/* default/group TX key index */
+	struct ieee80211_key iv_nw_keys[IEEE80211_WEP_NKID];
+	ieee80211_keyix_t (*iv_key_alloc)(struct ieee80211vap *, const struct ieee80211_key *);
+	int (*iv_key_delete)(struct ieee80211vap *, const struct ieee80211_key *,
+		struct ieee80211_node *);
+	int (*iv_key_set)(struct ieee80211vap *, const struct ieee80211_key *,
+		const u_int8_t mac[IEEE80211_ADDR_LEN]);
+	void (*iv_key_update_begin)(struct ieee80211vap *);
+	void (*iv_key_update_end)(struct ieee80211vap *);
+#ifdef ATH_SUPERG_COMP
+	void (*iv_comp_set)(struct ieee80211vap *, struct ieee80211_node *, int);
+#endif
+	const struct ieee80211_authenticator *iv_auth;	/* authenticator glue */
+	void *iv_ec;					/* private auth state */
+	struct ieee80211vap *iv_xrvap;			/* pointer to XR VAP , if XR is enabled */
+	u_int16_t iv_xrbcnwait;				/* SWBA count incremented until it reaches XR_BECON_FACTOR */
+	struct timer_list iv_xrvapstart;		/* timer to start xr */
+	u_int8_t iv_chanchange_count; 			/* 11h counter for channel change */
+	int iv_mcast_rate; 				/* Multicast rate (Kbps) */
+
+	const struct ieee80211_aclator *iv_acl;		/* aclator glue */
+	void *iv_as;					/* private aclator state */
+
+	struct timer_list iv_swbmiss;			/* software beacon miss timer */
+	u_int16_t iv_swbmiss_period; 			/* software beacon miss timer period */
+	struct ieee80211_nsparams iv_nsparams;		/* new state parameters for tasklet for stajoin1 */
+	struct IEEE80211_TQ_STRUCT iv_stajoin1tq; 	/* tasklet for newstate action called from stajoin1tq */
+	unsigned int iv_nsdone;				/* Done with scheduled newstate tasklet */
+	uint8_t	wds_mac[IEEE80211_ADDR_LEN];
+	struct ieee80211_spy iv_spy;         		/* IWSPY support */
+	struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
+	u_int32_t app_filter;				/* filters which management frames are forwarded to app */
+	int iv_maxrateindex;
+	int iv_minrateindex;
+};
+
+/* Debug functions need the defintion of struct ieee80211vap because iv_debug 
+ * is used at runtime to determine if we should log an event
+ */
+#include <net80211/ieee80211_debug.h>
+#include <net80211/ieee80211_node.h>
+#include <net80211/ieee80211_skb.h>
+
+struct ieee80211com {
+	struct net_device *ic_dev;		/* associated device */
+	ieee80211com_lock_t ic_comlock;		/* state update lock */
+	ieee80211com_lock_t ic_vapslock; 	/* vap state machine lock */
+	TAILQ_HEAD(, ieee80211vap) ic_vaps;	/* list of vap instances */
+	enum ieee80211_phytype ic_phytype;	/* XXX wrong for multi-mode */
+	enum ieee80211_opmode ic_opmode;	/* operation mode */
+	struct ifmedia ic_media;		/* interface media config */
+	u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
+	struct timer_list ic_inact;		/* mgmt/inactivity timer */
+
+	u_int32_t ic_flags;			/* state flags */
+	u_int32_t ic_flags_ext;			/* extension of state flags */
+	u_int32_t ic_caps;			/* capabilities */
+	u_int8_t ic_ath_cap;			/* Atheros adv. capabilities */
+	u_int8_t ic_promisc;			/* VAPs needing promisc mode */
+	u_int8_t ic_allmulti;			/* VAPs needing all multicast*/
+	u_int8_t ic_nopened;			/* VAPs been opened */
+	struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX];
+	struct ieee80211_rateset ic_sup_xr_rates;
+	struct ieee80211_rateset ic_sup_half_rates;
+	struct ieee80211_rateset ic_sup_quarter_rates;
+	u_int16_t ic_modecaps;			/* set of mode capabilities */
+	u_int16_t ic_curmode;			/* current mode */
+	u_int16_t ic_lintval;			/* beacon interval */
+	u_int16_t ic_holdover;			/* PM hold over duration */
+	u_int16_t ic_bmissthreshold;		/* beacon miss threshold (# beacons) */
+	unsigned long ic_bmiss_guard;		/* when to cease ignoring bmiss (jiffies) */
+	u_int16_t ic_txpowlimit; 		/* global tx power limit (in 0.5 dBm) */
+	u_int16_t ic_newtxpowlimit; 		/* tx power limit to change to (in 0.5 dBm) */
+	u_int16_t ic_uapsdmaxtriggers; 		/* max triggers that could arrive */
+	u_int8_t ic_coverageclass; 		/* coverage class */
+	u_int8_t ic_protmode_rssi;			/* rssi threshold for protection mode */
+	u_int64_t ic_protmode_lasttrig;		/* last trigger for protection mode */
+	u_int16_t ic_protmode_timeout;		/* protection mode timeout */
+
+	/* Channel state:
+	 *
+	 * ic_channels is the set of available channels for the device;
+	 *    it is setup by the driver
+	 * ic_nchans is the number of valid entries in ic_channels
+	 * ic_chan_avail is a bit vector of these channels used to check
+	 *    whether a channel is available w/o searching the channel table.
+	 * ic_chan_active is a (potentially) constrained subset of
+	 *    ic_chan_avail that reflects any mode setting or user-specified
+	 *    limit on the set of channels to use/scan
+	 * ic_curchan is the current channel the device is set to; it may
+	 *    be different from ic_bsschan when we are off-channel scanning
+	 *    or otherwise doing background work
+	 * ic_bsschan is the channel selected for operation; it may
+	 *    be undefined (IEEE80211_CHAN_ANYC)
+	 */
+	int ic_nchans;				/* # entries in ic_channels */
+	struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
+	struct timeval ic_chan_non_occupy[IEEE80211_CHAN_MAX];
+	u_int8_t ic_chan_avail[IEEE80211_CHAN_BYTES];
+	u_int8_t ic_chan_active[IEEE80211_CHAN_BYTES];
+	struct ieee80211_channel *ic_curchan;	/* current channel */
+	struct ieee80211_channel *ic_bsschan;	/* bss channel */
+	int16_t ic_channoise;			/* current channel noise in dBm */
+	struct timer_list ic_dfs_excl_timer;
+	/*
+	 * Spectrum management (IEEE 802.11h-2003):
+	 *
+	 * ic_chan_nodes is an array of numbers of nodes that provide
+	 *    ni_suppchans with the given channel reported as supported. Index
+	 *    of the array is an IEEE channel number (ic_ieee)
+	 * ic_cn_total is the number of nodes counted in ic_chan_nodes
+	 *    (provided ni_suppchans and are associated)
+	 * ic_sc_mincom is the desired minimum number of common channels, the
+	 *    parameter used by SC_TIGHT and SC_STRICT algorithms
+	 * ic_sc_algorithm is the algorithm for (re)association based on
+	 *    supported channels
+	 * ic_sc_slcg is the permil of Stations Lost per Channel Gained, the
+	 *    parameter used by SC_TIGHT and SC_STRICT algorithms. If due to
+	 *    association of the STA and disassociation of x other STAs (out of
+	 *    y associated STAs in total), the number of common channel
+	 *    increases by z, then such an action is performed if
+	 *    1000*x/y < z*ic_sc_slcg
+	 * ic_sc_sldg is the permil of Stations Lost per rssi Db Gained, the
+	 *    parameter used by SC_LOOSE algorithm. If due to the switch,
+	 *    the maximum RSSI of received packets on the current channel would
+	 *    decrease by z decibels and x stations from the set of y stations
+	 *    would be lost, then such a switch will be performed if
+	 *    1000*x/y < z*ic_sc_sldg
+	 * ic_sc_ie is the Supported Channels IE that is about to be sent along
+	 *    with (re)assoc requests (STA mode)
+	 */
+	u_int16_t ic_chan_nodes[IEEE80211_CHAN_MAX+1];
+	u_int16_t ic_cn_total;                  /* # nodes counted in ic_chan nodes */
+	u_int16_t ic_sc_mincom;                 /* minimum number of common channels */
+	enum ieee80211_sc_algorithm ic_sc_algorithm;
+	u_int16_t ic_sc_slcg;                   /* permil of Stations Lost per Channel Gained */
+	u_int16_t ic_sc_sldg;                   /* permil of Stations Lost per rssi Db Gained */
+	struct ieee80211_ie_sc ic_sc_ie;        /* Supported Channels IE */
+
+	/* Regulatory class ids */
+	u_int ic_nregclass;			/* # entries in ic_regclassids */
+	u_int8_t ic_regclassids[IEEE80211_REGCLASSIDS_MAX];
+
+	/* Scan-related state */
+	struct ieee80211_scan_state *ic_scan;	/* scan state */
+	enum ieee80211_roamingmode ic_roaming;	/* roaming mode */
+	unsigned long ic_lastdata;		/* time of last data frame */
+	unsigned long ic_lastscan;		/* time last scan completed */
+
+	/* NB: this is the union of all vap stations/neighbors */
+	struct ieee80211_node_table ic_sta;	/* stations/neighbors */
+
+	/* XXX Multi-BSS: split out common/VAP parts? */
+	struct ieee80211_wme_state ic_wme;	/* WME/WMM state */
+
+	/* XXX Multi-BSS: can per-VAP be done/make sense? */
+	enum ieee80211_protmode	ic_protmode;	/* 802.11g protection mode */
+	u_int16_t ic_nonerpsta;			/* # non-ERP stations */
+	u_int16_t ic_longslotsta;		/* # long slot time stations */
+	u_int16_t ic_sta_assoc;			/* stations associated */
+	u_int16_t ic_dt_sta_assoc;		/* dturbo capable stations */
+	u_int16_t ic_xr_sta_assoc;		/* XR stations associated */
+
+	/* Spectrum management. */
+	u_int16_t ic_country_code;
+	int ic_country_outdoor;
+	struct ieee80211_ie_country ic_country_ie; /* country info element */
+
+	/* current channel max power, used to compute Power Constraint IE.
+	 *
+	 * NB: local power constraint depends on the channel, but assuming it must
+	 *     be detected dynamically, we cannot maintain a table (i.e., will not
+	 *     know value until change to channel and detect).
+	 */
+	u_int8_t ic_curchanmaxpwr;
+	u_int8_t ic_chanchange_tbtt;
+	u_int8_t ic_chanchange_chan;
+
+	/* Global debug flags applicable to all VAPs */
+	int ic_debug;
+	/* used for reference tracking/counting.  Nodes are shared between VAPs,
+	 * so we put this here. */
+	atomic_t ic_node_counter;
+	/* Virtual AP create/delete */
+	struct ieee80211vap *(*ic_vap_create)(struct ieee80211com *,
+		const char *, int, int, struct net_device *);
+	void (*ic_vap_delete)(struct ieee80211vap *);
+
+	/* Send/recv 802.11 management frame */
+	int (*ic_send_mgmt)(struct ieee80211_node *, int, int);
+	void (*ic_recv_mgmt)(struct ieee80211vap *, struct ieee80211_node *,
+		struct sk_buff *, int, int, u_int64_t);
+
+	/* Send management frame to driver (like hardstart) */
+	int (*ic_mgtstart)(struct ieee80211com *, struct sk_buff *);
+
+	/* Reset device state after 802.11 parameter/state change */
+	int (*ic_init)(struct net_device *);
+	int (*ic_reset)(struct net_device *);
+
+	/* Update device state for 802.11 slot time change */
+	void (*ic_updateslot)(struct net_device *);
+
+	/* New station association callback/notification */
+	void (*ic_newassoc)(struct ieee80211_node *, int);
+
+	/* Node state management */
+	int32_t (*ic_node_count)(struct ieee80211com *);
+#ifdef IEEE80211_DEBUG_REFCNT
+	struct ieee80211_node *(*ic_node_alloc_debug)(struct ieee80211vap *, 
+			const char* func, int line);
+	void (*ic_node_cleanup_debug)(struct ieee80211_node *, 
+			const char* func, int line);
+	void (*ic_node_free_debug)(struct ieee80211_node *, 
+			const char* func, int line);
+#else
+	struct ieee80211_node *(*ic_node_alloc)(struct ieee80211vap *);
+	void (*ic_node_cleanup)(struct ieee80211_node *);
+	void (*ic_node_free)(struct ieee80211_node *);
+#endif
+
+	u_int8_t (*ic_node_getrssi)(const struct ieee80211_node *);
+	u_int8_t (*ic_node_move_data)(const struct ieee80211_node *);
+
+	/* Scanning support */
+	void (*ic_scan_start)(struct ieee80211com *);
+	void (*ic_scan_end)(struct ieee80211com *);
+	void (*ic_set_channel)(struct ieee80211com *);
+
+	/* U-APSD support */
+	void (*ic_uapsd_flush)(struct ieee80211_node *);
+
+	/* continuous transmission support */
+	void (*ic_set_txcont)(struct ieee80211com *, int);
+	int (*ic_get_txcont)(struct ieee80211com *);
+	void (*ic_set_txcont_power)(struct ieee80211com *, u_int);
+	int (*ic_get_txcont_power)(struct ieee80211com *);
+	void (*ic_set_txcont_rate)(struct ieee80211com *, u_int);
+	u_int (*ic_get_txcont_rate)(struct ieee80211com *);
+
+	/* DFS test mode prevents marking channel interference and channel 
+	 * switching during detection probability tests */
+	void (*ic_set_dfs_testmode)(struct ieee80211com *, int);
+	int (*ic_get_dfs_testmode)(struct ieee80211com *);
+
+	/* inject a fake radar signal -- used while on a 802.11h DFS channels */
+	unsigned int (*ic_test_radar)(struct ieee80211com *);
+
+#ifdef AR_DEBUG
+	/* dump HAL */
+	unsigned int (*ic_dump_hal_map)(struct ieee80211com *);
+#endif
+	/* DFS channel availability check time (in seconds) */
+	void (*ic_set_dfs_cac_time)(struct ieee80211com *, unsigned int);
+	unsigned int (*ic_get_dfs_cac_time)(struct ieee80211com *);
+
+	/* DFS non-occupancy period (in seconds) */
+	void (*ic_set_dfs_excl_period)(struct ieee80211com *, unsigned int);
+	unsigned int (*ic_get_dfs_excl_period)(struct ieee80211com *);
+
+	/* Set coverage class */
+	void (*ic_set_coverageclass)(struct ieee80211com *);
+
+	/* MHz to IEEE channel conversion */
+	u_int (*ic_mhz2ieee)(struct ieee80211com *, u_int, u_int);
+
+#ifdef ATH_REVERSE_ENGINEERING
+	/* debug and reverse engineering hooks */
+	void (*ic_registers_dump)(struct ieee80211com *);
+	void (*ic_registers_mark)(struct ieee80211com *);
+	void (*ic_registers_dump_delta)(struct ieee80211com *);
+	unsigned int (*ic_write_register)(struct ieee80211com *, unsigned int, unsigned int);
+	unsigned int (*ic_read_register)(struct ieee80211com *, unsigned int, unsigned int*);
+#endif /* #ifdef ATH_REVERSE_ENGINEERING */
+};
+
+#define MAX_PROC_IEEE80211_SIZE 16383
+#define PROC_IEEE80211_PERM 0644
+
+struct proc_ieee80211_priv {
+	int rlen;
+	int max_rlen;
+	char *rbuf;
+
+	int wlen;
+	int max_wlen;
+	char *wbuf;
+};
+
+struct ieee80211_proc_entry {
+	char *name;
+	struct file_operations *fileops;
+	struct proc_dir_entry *entry;
+	struct ieee80211_proc_entry *next;
+};
+
+MALLOC_DECLARE(M_80211_VAP);
+
+#define	IEEE80211_ADDR_NULL(a1)		(memcmp(a1, "\x00\x00\x00\x00\x00\x00", \
+					 IEEE80211_ADDR_LEN) == 0)
+#define	IEEE80211_ADDR_EQ(a1, a2)	(memcmp(a1, a2, IEEE80211_ADDR_LEN) == 0)
+#define	IEEE80211_ADDR_COPY(dst, src)	memcpy(dst, src, IEEE80211_ADDR_LEN)
+#define	IEEE80211_ADDR_SET_NULL(dst)	memset(dst, 0, IEEE80211_ADDR_LEN)
+
+/* ic_flags */
+#define	IEEE80211_F_FF		0x00000001		/* CONF: ATH FF enabled */
+#define	IEEE80211_F_TURBOP	0x00000002		/* CONF: ATH Turbo enabled*/
+#define	IEEE80211_F_PROMISC	0x00000004		/* STATUS: promiscuous mode */
+#define	IEEE80211_F_ALLMULTI	0x00000008		/* STATUS: all multicast mode */
+/* NB: this is intentionally setup to be IEEE80211_CAPINFO_PRIVACY */
+#define	IEEE80211_F_PRIVACY	0x00000010		/* CONF: privacy enabled */
+#define	IEEE80211_F_PUREG	0x00000020		/* CONF: 11g w/o 11b STAs */
+#define	IEEE80211_F_XRUPDATE	0x00000040		/* CONF: update beacon XR element*/
+#define	IEEE80211_F_SCAN	0x00000080		/* STATUS: scanning */
+#define	IEEE80211_F_XR		0x00000100		/* CONF: operate in XR mode */
+#define	IEEE80211_F_SIBSS	0x00000200		/* STATUS: start IBSS */
+/* NB: this is intentionally setup to be IEEE80211_CAPINFO_SHORT_SLOTTIME */
+#define	IEEE80211_F_SHSLOT	0x00000400		/* STATUS: use short slot time*/
+#define	IEEE80211_F_PMGTON	0x00000800		/* CONF: Power mgmt enable */
+#define	IEEE80211_F_DESBSSID	0x00001000		/* CONF: des_bssid is set */
+#define	IEEE80211_F_WME		0x00002000		/* CONF: enable WME use */
+#define	IEEE80211_F_BGSCAN	0x00004000		/* CONF: bg scan enabled */
+#define	IEEE80211_F_SWRETRY	0x00008000		/* CONF: sw tx retry enabled */
+#define IEEE80211_F_TXPOW_FIXED	0x00010000		/* TX Power: fixed rate */
+#define	IEEE80211_F_IBSSON	0x00020000		/* CONF: IBSS creation enable */
+#define	IEEE80211_F_SHPREAMBLE	0x00040000		/* STATUS: use short preamble */
+#define	IEEE80211_F_DATAPAD	0x00080000		/* CONF: do alignment pad */
+#define	IEEE80211_F_USEPROT	0x00100000		/* STATUS: protection enabled */
+#define	IEEE80211_F_USEBARKER	0x00200000		/* STATUS: use barker preamble*/
+#define	IEEE80211_F_TIMUPDATE	0x00400000		/* STATUS: update beacon tim */
+#define	IEEE80211_F_WPA1	0x00800000		/* CONF: WPA enabled */
+#define	IEEE80211_F_WPA2	0x01000000		/* CONF: WPA2 enabled */
+#define	IEEE80211_F_WPA		0x01800000		/* CONF: WPA/WPA2 enabled */
+#define	IEEE80211_F_DROPUNENC	0x02000000		/* CONF: drop unencrypted */
+#define	IEEE80211_F_COUNTERM	0x04000000		/* CONF: TKIP countermeasures */
+#define	IEEE80211_F_HIDESSID	0x08000000		/* CONF: hide SSID in beacon */
+#define IEEE80211_F_NOBRIDGE    0x10000000		/* CONF: disable internal bridge */
+
+#define	IEEE80211_F_WMEUPDATE	0x20000000		/* STATUS: update beacon wme */
+#define IEEE80211_F_DOTH	0x40000000		/* enable 11.h */
+#define IEEE80211_F_CHANSWITCH	0x80000000		/* force chanswitch */
+
+/* ic_flags_ext */
+#define	IEEE80211_FEXT_WDS		0x00000001	/* CONF: 4 addr allowed */
+#define IEEE80211_FEXT_COUNTRYIE	0x00000002	/* CONF: enable country IE */
+#define IEEE80211_FEXT_SCAN_PENDING	0x00000004	/* STATE: scan pending */
+#define	IEEE80211_FEXT_BGSCAN		0x00000008	/* STATE: enable full bgscan completion */
+#define IEEE80211_FEXT_UAPSD		0x00000010	/* CONF: enable U-APSD */
+#define IEEE80211_FEXT_SLEEP		0x00000020	/* STATUS: sleeping */
+#define IEEE80211_FEXT_EOSPDROP		0x00000040	/* drop uapsd EOSP frames for test */
+#define	IEEE80211_FEXT_MARKDFS		0x00000080	/* Enable marking of dfs interference */
+#define IEEE80211_FEXT_REGCLASS		0x00000100	/* CONF: send regclassids in country ie */
+#define IEEE80211_FEXT_ERPUPDATE	0x00000200	/* STATUS: update ERP element */
+#define IEEE80211_FEXT_SWBMISS		0x00000400	/* CONF: use software beacon timer */
+#define IEEE80211_FEXT_DROPUNENC_EAPOL	0x00000800	/* CONF: drop unencrypted eapol frames */
+#define IEEE80211_FEXT_APPIE_UPDATE	0x00001000	/* STATE: beacon APP IE updated */
+
+#define IEEE80211_COM_UAPSD_ENABLE(_ic)		((_ic)->ic_flags_ext |= IEEE80211_FEXT_UAPSD)
+#define IEEE80211_COM_UAPSD_DISABLE(_ic)	((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_UAPSD)
+#define IEEE80211_COM_UAPSD_ENABLED(_ic)	((_ic)->ic_flags_ext & IEEE80211_FEXT_UAPSD)
+#define IEEE80211_COM_GOTOSLEEP(_ic)		((_ic)->ic_flags_ext |= IEEE80211_FEXT_GOTOSLEEP)
+#define IEEE80211_COM_WAKEUP(_ic)		((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_SLEEP)
+#define IEEE80211_COM_IS_SLEEPING(_ic)		((_ic)->ic_flags_ext & IEEE80211_FEXT_SLEEP)
+
+#define IEEE80211_VAP_UAPSD_ENABLE(_v)		((_v)->iv_flags_ext |= IEEE80211_FEXT_UAPSD)
+#define IEEE80211_VAP_UAPSD_DISABLE(_v)		((_v)->iv_flags_ext &= ~IEEE80211_FEXT_UAPSD)
+#define IEEE80211_VAP_UAPSD_ENABLED(_v)		((_v)->iv_flags_ext & IEEE80211_FEXT_UAPSD)
+#define IEEE80211_VAP_GOTOSLEEP(_v)		((_v)->iv_flags_ext |= IEEE80211_FEXT_SLEEP)
+#define IEEE80211_VAP_WAKEUP(_v)		((_v)->iv_flags_ext &= ~IEEE80211_FEXT_SLEEP)
+#define IEEE80211_VAP_IS_SLEEPING(_v)		((_v)->iv_flags_ext & IEEE80211_FEXT_SLEEP)
+#define IEEE80211_VAP_EOSPDROP_ENABLE(_v)  	((_v)->iv_flags_ext |= IEEE80211_FEXT_EOSPDROP)
+#define IEEE80211_VAP_EOSPDROP_DISABLE(_v) 	((_v)->iv_flags_ext &= ~IEEE80211_FEXT_EOSPDROP)
+#define IEEE80211_VAP_EOSPDROP_ENABLED(_v) 	((_v)->iv_flags_ext & IEEE80211_FEXT_EOSPDROP)
+#define IEEE80211_VAP_DROPUNENC_EAPOL_ENABLE(_v) \
+						((_v)->iv_flags_ext |= IEEE80211_FEXT_DROPUNENC_EAPOL)
+#define IEEE80211_VAP_DROPUNENC_EAPOL_DISABLE(_v) \
+						((_v)->iv_flags_ext &= ~IEEE80211_FEXT_DROPUNENC_EAPOL)
+#define IEEE80211_VAP_DROPUNENC_EAPOL(_v) 	((_v)->iv_flags_ext & IEEE80211_FEXT_DROPUNENC_EAPOL)
+
+
+/* ic_caps */
+#define	IEEE80211_C_WEP		0x00000001	/* CAPABILITY: WEP available */
+#define	IEEE80211_C_TKIP	0x00000002	/* CAPABILITY: TKIP available */
+#define	IEEE80211_C_AES		0x00000004	/* CAPABILITY: AES OCB avail */
+#define	IEEE80211_C_AES_CCM	0x00000008	/* CAPABILITY: AES CCM avail */
+#define	IEEE80211_C_CKIP	0x00000020	/* CAPABILITY: CKIP available */
+#define	IEEE80211_C_FF		0x00000040	/* CAPABILITY: ATH FF avail */
+#define	IEEE80211_C_TURBOP	0x00000080	/* CAPABILITY: ATH Turbo avail*/
+#define	IEEE80211_C_IBSS	0x00000100	/* CAPABILITY: IBSS available */
+#define	IEEE80211_C_PMGT	0x00000200	/* CAPABILITY: Power mgmt */
+#define	IEEE80211_C_HOSTAP	0x00000400	/* CAPABILITY: HOSTAP avail */
+#define	IEEE80211_C_AHDEMO	0x00000800	/* CAPABILITY: Old Adhoc Demo */
+#define	IEEE80211_C_SWRETRY	0x00001000	/* CAPABILITY: sw tx retry */
+#define	IEEE80211_C_TXPMGT	0x00002000	/* CAPABILITY: tx power mgmt */
+#define	IEEE80211_C_SHSLOT	0x00004000	/* CAPABILITY: short slottime */
+#define	IEEE80211_C_SHPREAMBLE	0x00008000	/* CAPABILITY: short preamble */
+#define	IEEE80211_C_MONITOR	0x00010000	/* CAPABILITY: monitor mode */
+#define	IEEE80211_C_TKIPMIC	0x00020000	/* CAPABILITY: TKIP MIC avail */
+#define	IEEE80211_C_WPA1	0x00800000	/* CAPABILITY: WPA1 avail */
+#define	IEEE80211_C_WPA2	0x01000000	/* CAPABILITY: WPA2 avail */
+#define	IEEE80211_C_WPA		0x01800000	/* CAPABILITY: WPA1+WPA2 avail*/
+#define	IEEE80211_C_BURST	0x02000000	/* CAPABILITY: frame bursting */
+#define	IEEE80211_C_WME		0x04000000	/* CAPABILITY: WME avail */
+#define	IEEE80211_C_WDS		0x08000000	/* CAPABILITY: 4-addr support */
+#define IEEE80211_C_WME_TKIPMIC	0x10000000	/* CAPABILITY: TKIP MIC for QoS frame */
+#define	IEEE80211_C_BGSCAN	0x20000000	/* CAPABILITY: bg scanning */
+#define	IEEE80211_C_UAPSD	0x40000000	/* CAPABILITY: UAPSD */
+/* XXX protection/barker? */
+
+#define	IEEE80211_C_CRYPTO	0x0000002f	/* CAPABILITY: crypto alg's */
+
+/* Atheros ABOLT definitions */
+#define IEEE80211_ABOLT_TURBO_G		0x01	/* Legacy Turbo G */
+#define IEEE80211_ABOLT_TURBO_PRIME	0x02	/* Turbo Prime */
+#define IEEE80211_ABOLT_COMPRESSION	0x04	/* Compression */
+#define IEEE80211_ABOLT_FAST_FRAME	0x08	/* Fast Frames */
+#define IEEE80211_ABOLT_BURST		0x10	/* Bursting */
+#define IEEE80211_ABOLT_WME_ELE		0x20	/* WME based cwmin/max/burst tuning */
+#define IEEE80211_ABOLT_XR		0x40	/* XR */
+#define IEEE80211_ABOLT_AR		0x80	/* AR switches out based on adjaced non-turbo traffic */
+
+/* Atheros Advanced Capabilities ABOLT definition */
+#define IEEE80211_ABOLT_ADVCAP	(IEEE80211_ABOLT_TURBO_PRIME | \
+				 IEEE80211_ABOLT_COMPRESSION | \
+				 IEEE80211_ABOLT_FAST_FRAME | \
+				 IEEE80211_ABOLT_XR | \
+				 IEEE80211_ABOLT_AR | \
+				 IEEE80211_ABOLT_BURST | \
+				 IEEE80211_ABOLT_WME_ELE)
+
+/* check if a capability was negotiated for use */
+#define	IEEE80211_ATH_CAP(vap, ni, bit) \
+	((ni)->ni_ath_flags & (vap)->iv_ath_cap & (bit))
+
+/* flags to VAP create function */
+#define IEEE80211_VAP_XR		0x10000	/* create a XR VAP without registering net device with OS */
+
+int ieee80211_ifattach(struct ieee80211com *);
+void ieee80211_ifdetach(struct ieee80211com *);
+int ieee80211_vap_setup(struct ieee80211com *, struct net_device *,
+	const char *, int, int);
+int ieee80211_vap_attach(struct ieee80211vap *, ifm_change_cb_t, ifm_stat_cb_t);
+void ieee80211_vap_detach(struct ieee80211vap *);
+void ieee80211_mark_dfs(struct ieee80211com *, struct ieee80211_channel *);
+void ieee80211_dfs_test_return(struct ieee80211com *, u_int8_t);
+void ieee80211_announce(struct ieee80211com *);
+void ieee80211_announce_channels(struct ieee80211com *);
+int ieee80211_media_change(struct net_device *);
+void ieee80211_media_status(struct net_device *, struct ifmediareq *);
+int ieee80211_rate2media(struct ieee80211com*, int, enum ieee80211_phymode);
+int ieee80211_media2rate(int);
+u_int ieee80211_mhz2ieee(u_int, u_int);
+u_int ieee80211_chan2ieee(struct ieee80211com *,	const struct ieee80211_channel *);
+u_int ieee80211_ieee2mhz(u_int, u_int);
+struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *, int, int);
+int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
+void ieee80211_reset_erp(struct ieee80211com *, enum ieee80211_phymode);
+enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
+void ieee80211_build_countryie(struct ieee80211com *);
+int ieee80211_media_setup(struct ieee80211com *, struct ifmedia *, u_int32_t,
+	ifm_change_cb_t, ifm_stat_cb_t);
+void ieee80211_build_sc_ie(struct ieee80211com *);
+void ieee80211_dfs_action(struct ieee80211com *);
+void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
+void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
+
+/*
+ * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
+ * It relies on the assumption that ic_ieee cannot be 0 and that all the
+ * duplicates in ic_channels occur subsequently.
+ *
+ * _i and _prevchan are temporary variables
+ */
+#define CHANNEL_FOREACH(_chan, _ic, _i, _prevchan)			\
+	for ((_i) = 0, (_prevchan) = 0;					\
+	     (_i) < (_ic)->ic_nchans && ((_chan) =			\
+		     (_ic)->ic_channels[(_i)].ic_ieee);			\
+	     (_prevchan) = (_chan), (_i)++				\
+	    ) if ((_chan) != (_prevchan))
+
+/* Key update synchronization methods.  XXX should not be visible. */
+static __inline void
+ieee80211_key_update_begin(struct ieee80211vap *vap)
+{
+	vap->iv_key_update_begin(vap);
+}
+static __inline void
+ieee80211_key_update_end(struct ieee80211vap *vap)
+{
+	vap->iv_key_update_end(vap);
+}
+
+/* XXX these need to be here for IEEE80211_F_DATAPAD */
+
+/*
+ * Return the space occupied by the 802.11 header and any
+ * padding required by the driver.  This works for a
+ * management or data frame.
+ */
+static __inline int
+ieee80211_hdrspace(struct ieee80211com *ic, const void *data)
+{
+	int size = ieee80211_hdrsize(data);
+	if (ic->ic_flags & IEEE80211_F_DATAPAD)
+		size = roundup(size, sizeof(u_int32_t));
+	return size;
+}
+
+/* Like ieee80211_hdrspace, but handles any type of frame. */
+static __inline int
+ieee80211_anyhdrspace(struct ieee80211com *ic, const void *data)
+{
+	int size = ieee80211_anyhdrsize(data);
+	if (ic->ic_flags & IEEE80211_F_DATAPAD)
+		size = roundup(size, sizeof(u_int32_t));
+	return size;
+}
+
+/* Macros to print MAC address used in 802.11 headers */
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ADDR(addr) \
+  ((unsigned char *)(addr)) [0], \
+  ((unsigned char *)(addr)) [1], \
+  ((unsigned char *)(addr)) [2], \
+  ((unsigned char *)(addr)) [3], \
+  ((unsigned char *)(addr)) [4], \
+  ((unsigned char *)(addr)) [5]
+
+#endif /* _NET80211_IEEE80211_VAR_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_athproto.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_athproto.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_athproto.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_athproto.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2004 Atheros Communications Inc.  All rights reserved.
+ *
+ * $Id: if_athproto.h 2888 2007-11-21 10:45:58Z mtaylor $
+ */
+
+#ifndef _NET_IF_ATH_PROTO_H_
+#define _NET_IF_ATH_PROTO_H_
+
+/*
+ * Atheros proprietary protocol info.
+ */
+
+/*
+ * Atheros RSSI, Signal, Noise, etc.
+ */
+
+#define ATH_DEFAULT_NOISE	-95	/* dBm */
+
+/*
+ * Atheros proprietary SuperG defines.
+ */
+
+#define ATH_ETH_TYPE  		0x88bd
+#define ATH_SNAP_ORGCODE_0	0x00
+#define ATH_SNAP_ORGCODE_1	0x03
+#define ATH_SNAP_ORGCODE_2	0x7f
+
+struct athl2p_tunnel_hdr {
+#if (_BYTE_ORDER == _LITTLE_ENDIAN)
+	u_int32_t offset:11,
+	seqNum:11,
+	optHdrLen32:2,
+	frameType:2,
+	proto:6;
+#else /* big endian */
+	u_int32_t proto:6,
+	frameType:2,
+	optHdrLen32:2,
+	seqNum:11,
+	offset:11;
+#endif
+} __packed;
+
+/*
+ * The following defines control compiling Atheros-specific features
+ * (see BuildCaps.inc):
+ *
+ *   ATH_SUPERG_FF 
+ *      set to 1 for fast-frame
+ */
+
+#define ATH_L2TUNNEL_PROTO_FF 0
+/* FF max payload: 
+ * 802.2 + FFHDR + HPAD + 802.3 + 802.2 + 1500 + SPAD + 802.3 + 802.2 + 1500:
+ *   8   +   4   +  4   +   14  +   8   + 1500 +  6   +   14  +   8   + 1500
+ * = 3066
+ */
+#define ATH_FF_MAX_HDR_PAD	4
+#define ATH_FF_MAX_SEP_PAD	6
+#define ATH_FF_MAX_HDR		30
+#define ATH_FF_MAX_PAYLOAD 	3066
+#define ATH_FF_MAX_LEN (ATH_FF_MAX_PAYLOAD + IEEE80211_CRC_LEN + \
+	(IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))
+
+/*
+ * Store a magic number in skb->cb[] area to indicate FF within driver.
+ * Offset of 8B into cb[] is used to preserve vlan tag info.
+ */
+#define ATH_FF_MAGIC_PUT(_skb) \
+	(SKB_CB(_skb)->flags |= M_FF)
+#define ATH_FF_MAGIC_CLR(_skb) \
+	(SKB_CB(_skb)->flags &= ~M_FF)
+#define ATH_FF_MAGIC_PRESENT(_skb) \
+	((SKB_CB(_skb)->flags & M_FF) != 0)
+#define ATH_FF_NEXTSKB_PUT(_skb, _next) \
+	(SKB_CB(_skb)->next = _next)
+#define ATH_FF_NEXTSKB_GET(_skb) \
+	(SKB_CB(_skb)->next)
+
+/*
+ * default value for the minimum txq depth required for an ath_buf to be
+ * placed on the FF staging queue. this value should be >=3 due to interaction
+ * with HW compression.
+ */
+#define ATH_FF_TXQMIN		3
+
+/* 
+ * default maximum age an ath_buf is allowed to remain on the staging queue.
+ * When this number of ath_bufs have been queued on the txq, after an ath_buf
+ * was placed on the staging queue, that ath_buf on the staging queue will be
+ * flushed.
+ */
+#define ATH_FF_STAGEQAGEMAX	5
+
+/*
+ * Reserve enough buffer header length to avoid reallocation on fast-frame
+ * rx and tx.
+ */
+#define USE_HEADERLEN_RESV	1
+
+#endif /* _NET_IF_ATH_PROTO_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_ethersubr.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_ethersubr.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_ethersubr.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_ethersubr.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: if_ethersubr.h 2028 2007-01-30 03:51:52Z proski $
+ */
+
+#ifndef _NET_IF_ETHERSUBR_H_
+#define _NET_IF_ETHERSUBR_H_
+
+#define	ETHER_ADDR_LEN		6	/* length of an Ethernet address */
+#define	ETHER_TYPE_LEN		2	/* length of the Ethernet type field */
+#define	ETHER_CRC_LEN		4	/* length of the Ethernet CRC */
+#define	ETHER_HDR_LEN		(ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+#define	ETHER_MAX_LEN		1518
+
+#define	ETHERMTU	(ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
+
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct	ether_header {
+	u_char ether_dhost[ETHER_ADDR_LEN];
+	u_char ether_shost[ETHER_ADDR_LEN];
+	__be16 ether_type;
+} __packed;
+
+#ifndef ETHERTYPE_PAE
+#define	ETHERTYPE_PAE	0x888e		/* EAPOL PAE/802.1x */
+#endif
+#ifndef ETHERTYPE_IP
+#define	ETHERTYPE_IP	0x0800		/* IP protocol */
+#endif
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct	ether_addr {
+	u_char octet[ETHER_ADDR_LEN];
+} __packed;
+
+#define	ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
+
+#define VLAN_PRI_SHIFT	13		/* Shift to find VLAN user priority */
+#define VLAN_PRI_MASK	7		/* Mask for user priority bits in VLAN */
+
+
+#endif /* _NET_IF_ETHERSUBR_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_llc.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_llc.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_llc.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_llc.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,193 @@
+/*-
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: if_llc.h 2028 2007-01-30 03:51:52Z proski $
+ */
+
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NET_IF_LLC_H_
+#define _NET_IF_LLC_H_
+
+/*
+ * IEEE 802.2 Link Level Control headers, for use in conjunction with
+ * 802.{3,4,5} media access control methods.
+ *
+ * Headers here do not use bit fields due to shortcomings in many
+ * compilers.
+ */
+
+struct llc {
+	u_int8_t llc_dsap;
+	u_int8_t llc_ssap;
+	union {
+	    struct {
+		u_int8_t control;
+		u_int8_t format_id;
+		u_int8_t class;
+		u_int8_t window_x2;
+	    } __packed type_u;
+	    struct {
+		u_int8_t num_snd_x2;
+		u_int8_t num_rcv_x2;
+	    } __packed type_i;
+	    struct {
+		u_int8_t control;
+		u_int8_t num_rcv_x2;
+	    } __packed type_s;
+	    struct {
+	        u_int8_t control;
+		/*
+		 * We cannot put the following fields in a structure because
+		 * the structure rounding might cause padding.
+		 */
+		u_int8_t frmr_rej_pdu0;
+		u_int8_t frmr_rej_pdu1;
+		u_int8_t frmr_control;
+		u_int8_t frmr_control_ext;
+		u_int8_t frmr_cause;
+	    } __packed type_frmr;
+	    struct {
+		u_int8_t control;
+		u_int8_t org_code[3];
+		__be16 ether_type;
+	    } __packed type_snap;
+	    struct {
+		u_int8_t control;
+		u_int8_t control_ext;
+	    } __packed type_raw;
+	} llc_un /* XXX __packed ??? */;
+} __packed;
+
+struct frmrinfo {
+	u_int8_t frmr_rej_pdu0;
+	u_int8_t frmr_rej_pdu1;
+	u_int8_t frmr_control;
+	u_int8_t frmr_control_ext;
+	u_int8_t frmr_cause;
+} __packed;
+
+#define	llc_control		llc_un.type_u.control
+#define	llc_control_ext		llc_un.type_raw.control_ext
+#define	llc_fid			llc_un.type_u.format_id
+#define	llc_class		llc_un.type_u.class
+#define	llc_window		llc_un.type_u.window_x2
+#define	llc_frmrinfo 		llc_un.type_frmr.frmr_rej_pdu0
+#define	llc_frmr_pdu0		llc_un.type_frmr.frmr_rej_pdu0
+#define	llc_frmr_pdu1		llc_un.type_frmr.frmr_rej_pdu1
+#define	llc_frmr_control	llc_un.type_frmr.frmr_control
+#define	llc_frmr_control_ext	llc_un.type_frmr.frmr_control_ext
+#define	llc_frmr_cause		llc_un.type_frmr.frmr_cause
+#define	llc_snap		llc_un.type_snap
+
+/*
+ * Don't use sizeof(struct llc_un) for LLC header sizes
+ */
+#define LLC_ISFRAMELEN 4
+#define LLC_UFRAMELEN  3
+#define LLC_FRMRLEN    7
+#define LLC_SNAPFRAMELEN 8
+
+/*
+ * Unnumbered LLC format commands
+ */
+#define LLC_UI		0x3
+#define LLC_UI_P	0x13
+#define LLC_DISC	0x43
+#define	LLC_DISC_P	0x53
+#define LLC_UA		0x63
+#define LLC_UA_P	0x73
+#define LLC_TEST	0xe3
+#define LLC_TEST_P	0xf3
+#define LLC_FRMR	0x87
+#define	LLC_FRMR_P	0x97
+#define LLC_DM		0x0f
+#define	LLC_DM_P	0x1f
+#define LLC_XID		0xaf
+#define LLC_XID_P	0xbf
+#define LLC_SABME	0x6f
+#define LLC_SABME_P	0x7f
+
+/*
+ * Supervisory LLC commands
+ */
+#define	LLC_RR		0x01
+#define	LLC_RNR		0x05
+#define	LLC_REJ		0x09
+
+/*
+ * Info format - dummy only
+ */
+#define	LLC_INFO	0x00
+
+/*
+ * ISO PDTR 10178 contains among others
+ */
+#define LLC_X25_LSAP	0x7e
+#define LLC_SNAP_LSAP	0xaa
+#define LLC_ISO_LSAP	0xfe
+
+#endif /* _NET_IF_LLC_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_media.h kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_media.h
--- kamikaze_7.09.orig/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_media.h	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/kmod-madwifi/usr/include/madwifi/net80211/if_media.h	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,497 @@
+/*	$NetBSD: if_media.h,v 1.3 1997/03/26 01:19:27 thorpej Exp $	*/
+/* $FreeBSD: src/sys/net/if_media.h,v 1.18 2002/07/14 21:58:19 kbyanc Exp $ */
+/*	$Id: if_media.h 2864 2007-11-20 17:18:36Z proski $	*/
+
+/*
+ * Copyright (c) 1997
+ *	Jonathan Stone and Jason R. Thorpe.  All rights reserved.
+ *
+ * This software is derived from information provided by Matt Thomas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Jonathan Stone
+ *	and Jason R. Thorpe for the NetBSD Project.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: if_media.h 2864 2007-11-20 17:18:36Z proski $
+ */
+
+#ifndef _NET_IF_MEDIA_H_
+#define _NET_IF_MEDIA_H_
+
+#include <net80211/ieee80211_linux.h>
+
+/*
+ * Prototypes and definitions for BSD/OS-compatible network interface
+ * media selection.
+ *
+ * Where it is safe to do so, this code strays slightly from the BSD/OS
+ * design.  Software which uses the API (device drivers, basically)
+ * shouldn't notice any difference.
+ *
+ * Many thanks to Matt Thomas for providing the information necessary
+ * to implement this interface.
+ */
+
+struct ifmediareq {
+	char ifm_name[IFNAMSIZ];	/* if name, e.g. "en0" */
+	int ifm_current;			/* current media options */
+	int ifm_mask;			/* don't care mask */
+	int ifm_status;			/* media status */
+	int ifm_active;			/* active options */
+	int ifm_count;			/* # entries in ifm_ulist array */
+	int __user *ifm_ulist;		/* media words */
+};
+#define	SIOCSIFMEDIA	_IOWR('i', 55, struct ifreq)	/* set net media */
+#define	SIOCGIFMEDIA	_IOWR('i', 56, struct ifmediareq) /* get net media */
+
+#ifdef __KERNEL__
+
+#include <sys/queue.h>
+
+/*
+ * Driver callbacks for media status and change requests.
+ */
+struct net_device;
+typedef	int (*ifm_change_cb_t)(struct net_device *);
+typedef	void (*ifm_stat_cb_t)(struct net_device *, struct ifmediareq *);
+
+/*
+ * In-kernel representation of a single supported media type.
+ */
+struct ifmedia_entry {
+	LIST_ENTRY(ifmedia_entry) ifm_list;
+	int ifm_media;		/* description of this media attachment */
+	int ifm_data;		/* for driver-specific use */
+	void *ifm_aux;		/* for driver-specific use */
+};
+
+/*
+ * One of these goes into a network interface's softc structure.
+ * It is used to keep general media state.
+ */
+struct ifmedia {
+	int ifm_mask;			/* mask of changes we don't care about */
+	int ifm_media;			/* current user-set media word */
+	struct ifmedia_entry *ifm_cur;	/* currently selected media */
+	ATH_LIST_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */
+	ifm_change_cb_t	ifm_change;	/* media change driver callback */
+	ifm_stat_cb_t ifm_status;	/* media status driver callback */
+};
+
+/* Initialize an interface's struct if_media field. */
+void ifmedia_init(struct ifmedia *, int, ifm_change_cb_t, ifm_stat_cb_t);
+
+/* Remove all mediums from a struct ifmedia.  */
+void ifmedia_removeall(struct ifmedia *);
+
+/* Add one supported medium to a struct ifmedia. */
+void ifmedia_add(struct ifmedia *, int, int, void *);
+
+/* Add an array (of ifmedia_entry) media to a struct ifmedia. */
+void ifmedia_list_add(struct ifmedia *, struct ifmedia_entry *, int);
+
+/* Set default media type on initialization. */
+void ifmedia_set(struct ifmedia *, int);
+
+/* Common ioctl function for getting/setting media, called by driver. */
+int ifmedia_ioctl(struct net_device *, struct ifreq *, struct ifmedia *, u_long);
+
+#endif /*_KERNEL */
+
+/*
+ * if_media Options word:
+ *	Bits	Use
+ *	----	-------
+ *	0-4	Media variant
+ *	5-7	Media type
+ *	8-15	Type specific options
+ *	16-18	Mode (for multi-mode devices)
+ *	19	RFU
+ *	20-27	Shared (global) options
+ *	28-31	Instance
+ */
+
+/*
+ * Ethernet
+ */
+#define	IFM_ETHER	0x00000020
+#define	IFM_10_T	3		/* 10BaseT - RJ45 */
+#define	IFM_10_2	4		/* 10Base2 - Thinnet */
+#define	IFM_10_5	5		/* 10Base5 - AUI */
+#define	IFM_100_TX	6		/* 100BaseTX - RJ45 */
+#define	IFM_100_FX	7		/* 100BaseFX - Fiber */
+#define	IFM_100_T4	8		/* 100BaseT4 - 4 pair cat 3 */
+#define	IFM_100_VG	9		/* 100VG-AnyLAN */
+#define	IFM_100_T2	10		/* 100BaseT2 */
+#define	IFM_1000_SX	11		/* 1000BaseSX - multi-mode fiber */
+#define	IFM_10_STP	12		/* 10BaseT over shielded TP */
+#define	IFM_10_FL	13		/* 10BaseFL - Fiber */
+#define	IFM_1000_LX	14		/* 1000baseLX - single-mode fiber */
+#define	IFM_1000_CX	15		/* 1000baseCX - 150ohm STP */
+#define	IFM_1000_T	16		/* 1000baseT - 4 pair cat 5 */
+#define	IFM_HPNA_1	17		/* HomePNA 1.0 (1Mb/s) */
+/* note 31 is the max! */
+
+#define	IFM_ETH_MASTER	0x00000100	/* master mode (1000baseT) */
+
+/*
+ * Token ring
+ */
+#define	IFM_TOKEN	0x00000040
+#define	IFM_TOK_STP4	3		/* Shielded twisted pair 4m - DB9 */
+#define	IFM_TOK_STP16	4		/* Shielded twisted pair 16m - DB9 */
+#define	IFM_TOK_UTP4	5		/* Unshielded twisted pair 4m - RJ45 */
+#define	IFM_TOK_UTP16	6		/* Unshielded twisted pair 16m - RJ45 */
+#define	IFM_TOK_STP100  7		/* Shielded twisted pair 100m - DB9 */
+#define	IFM_TOK_UTP100  8		/* Unshielded twisted pair 100m - RJ45 */
+#define	IFM_TOK_ETR	0x00000200	/* Early token release */
+#define	IFM_TOK_SRCRT	0x00000400	/* Enable source routing features */
+#define	IFM_TOK_ALLR	0x00000800	/* All routes / Single route bcast */
+#define	IFM_TOK_DTR	0x00002000	/* Dedicated token ring */
+#define	IFM_TOK_CLASSIC	0x00004000	/* Classic token ring */
+#define	IFM_TOK_AUTO	0x00008000	/* Automatic Dedicate/Classic token ring */
+
+/*
+ * FDDI
+ */
+#define	IFM_FDDI	0x00000060
+#define	IFM_FDDI_SMF	3		/* Single-mode fiber */
+#define	IFM_FDDI_MMF	4		/* Multi-mode fiber */
+#define	IFM_FDDI_UTP	5		/* CDDI / UTP */
+#define	IFM_FDDI_DA	0x00000100	/* Dual attach / single attach */
+
+/*
+ * IEEE 802.11 Wireless
+ */
+#define	IFM_IEEE80211	0x00000080
+/* NB: 0,1,2 are auto, manual, none defined below */
+#define	IFM_IEEE80211_FH1	3	/* Frequency Hopping 1Mbps */
+#define	IFM_IEEE80211_FH2	4	/* Frequency Hopping 2Mbps */
+#define	IFM_IEEE80211_DS1	5	/* Direct Sequence 1Mbps */
+#define	IFM_IEEE80211_DS2	6	/* Direct Sequence 2Mbps */
+#define	IFM_IEEE80211_DS5	7	/* Direct Sequence 5.5Mbps */
+#define	IFM_IEEE80211_DS11	8	/* Direct Sequence 11Mbps */
+#define	IFM_IEEE80211_DS22	9	/* Direct Sequence 22Mbps */
+#define IFM_IEEE80211_OFDM1_50  10      /* OFDM 1.5Mbps */
+#define IFM_IEEE80211_OFDM2_25  11      /* OFDM 2.25Mbps */
+#define IFM_IEEE80211_OFDM3     12      /* OFDM 3Mbps */
+#define IFM_IEEE80211_OFDM4_50  13      /* OFDM 4.5Mbps */
+#define IFM_IEEE80211_OFDM6     14      /* OFDM 6Mbps */
+#define IFM_IEEE80211_OFDM9     15      /* OFDM 9Mbps */
+#define IFM_IEEE80211_OFDM12    16      /* OFDM 12Mbps */
+#define IFM_IEEE80211_OFDM13_5  17      /* OFDM 13.5Mpbs */
+#define IFM_IEEE80211_OFDM18    18      /* OFDM 18Mbps */
+#define IFM_IEEE80211_OFDM24    19      /* OFDM 24Mbps */
+#define IFM_IEEE80211_OFDM27    20      /* OFDM 27Mbps */
+#define IFM_IEEE80211_OFDM36    21      /* OFDM 36Mbps */
+#define IFM_IEEE80211_OFDM48    22      /* OFDM 48Mbps */
+#define IFM_IEEE80211_OFDM54    23      /* OFDM 54Mbps */
+#define IFM_IEEE80211_OFDM72    24      /* OFDM 72Mbps */
+
+#define	IFM_IEEE80211_ADHOC	0x00000100	/* Operate in Adhoc mode */
+#define	IFM_IEEE80211_HOSTAP	0x00000200	/* Operate in Host AP mode */
+#define	IFM_IEEE80211_IBSS	0x00000400	/* Operate in IBSS mode */
+#define	IFM_IEEE80211_WDS	0x00000800	/* Operate in WDS mode */
+#define	IFM_IEEE80211_TURBO	0x00001000	/* Operate in turbo mode */
+#define	IFM_IEEE80211_MONITOR	0x00002000	/* Operate in monitor mode */
+
+/* operating mode for multi-mode devices */
+#define	IFM_IEEE80211_11A	0x00010000	/* 5Ghz, OFDM mode */
+#define	IFM_IEEE80211_11B	0x00020000	/* Direct Sequence mode */
+#define	IFM_IEEE80211_11G	0x00030000	/* 2Ghz, CCK mode */
+#define	IFM_IEEE80211_FH	0x00040000	/* 2Ghz, GFSK mode */
+
+/*
+ * Shared media sub-types
+ */
+#define	IFM_AUTO	0		/* Autoselect best media */
+#define	IFM_MANUAL	1		/* Jumper/dipswitch selects media */
+#define	IFM_NONE	2		/* Deselect all media */
+
+/*
+ * Shared options
+ */
+#define	IFM_FDX		0x00100000	/* Force full duplex */
+#define	IFM_HDX		0x00200000	/* Force half duplex */
+#define	IFM_FLAG0	0x01000000	/* Driver defined flag */
+#define	IFM_FLAG1	0x02000000	/* Driver defined flag */
+#define	IFM_FLAG2	0x04000000	/* Driver defined flag */
+#define	IFM_LOOP	0x08000000	/* Put hardware in loopback */
+
+/*
+ * Masks
+ */
+#define	IFM_NMASK	0x000000e0	/* Network type */
+#define	IFM_TMASK	0x0000001f	/* Media sub-type */
+#define	IFM_IMASK	0xf0000000	/* Instance */
+#define	IFM_ISHIFT	28		/* Instance shift */
+#define	IFM_OMASK	0x0000ff00	/* Type specific options */
+#define	IFM_MMASK	0x00070000	/* Mode */
+#define	IFM_MSHIFT	16		/* Mode shift */
+#define	IFM_GMASK	0x0ff00000	/* Global options */
+
+/*
+ * Status bits
+ */
+#define	IFM_AVALID	0x00000001	/* Active bit valid */
+#define	IFM_ACTIVE	0x00000002	/* Interface attached to working net */
+
+/*
+ * Macros to extract various bits of information from the media word.
+ */
+#define	IFM_TYPE(x)		((x) & IFM_NMASK)
+#define	IFM_SUBTYPE(x)		((x) & IFM_TMASK)
+#define	IFM_TYPE_OPTIONS(x)	((x) & IFM_OMASK)
+#define	IFM_INST(x)		(((x) & IFM_IMASK) >> IFM_ISHIFT)
+#define	IFM_OPTIONS(x)		((x) & (IFM_OMASK|IFM_GMASK))
+#define	IFM_MODE(x)		((x) & IFM_MMASK)
+
+#define	IFM_INST_MAX		IFM_INST(IFM_IMASK)
+
+/*
+ * Macro to create a media word.
+ */
+#define	IFM_MAKEWORD(type, subtype, options, instance)			\
+	((type) | (subtype) | (options) | ((instance) << IFM_ISHIFT))
+#define	IFM_MAKEMODE(mode) \
+	(((mode) << IFM_MSHIFT) & IFM_MMASK)
+
+/*
+ * NetBSD extension not defined in the BSDI API.  This is used in various
+ * places to get the canonical description for a given type/subtype.
+ *
+ * NOTE: all but the top-level type descriptions must contain NO whitespace!
+ * Otherwise, parsing these in ifconfig(8) would be a nightmare.
+ */
+struct ifmedia_description {
+	int	ifmt_word;		/* word value; may be masked */
+	const char *ifmt_string;	/* description */
+};
+
+#define	IFM_TYPE_DESCRIPTIONS {						\
+	{ IFM_ETHER,		"Ethernet" },				\
+	{ IFM_TOKEN,		"Token ring" },				\
+	{ IFM_FDDI,		"FDDI" },				\
+	{ IFM_IEEE80211,	"IEEE 802.11 Wireless Ethernet" },	\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_ETHERNET_DESCRIPTIONS {				\
+	{ IFM_10_T,	"10baseT/UTP" },				\
+	{ IFM_10_2,	"10base2/BNC" },				\
+	{ IFM_10_5,	"10base5/AUI" },				\
+	{ IFM_100_TX,	"100baseTX" },					\
+	{ IFM_100_FX,	"100baseFX" },					\
+	{ IFM_100_T4,	"100baseT4" },					\
+	{ IFM_100_VG,	"100baseVG" },					\
+	{ IFM_100_T2,	"100baseT2" },					\
+	{ IFM_10_STP,	"10baseSTP" },					\
+	{ IFM_10_FL,	"10baseFL" },					\
+	{ IFM_1000_SX,	"1000baseSX" },					\
+	{ IFM_1000_LX,	"1000baseLX" },					\
+	{ IFM_1000_CX,	"1000baseCX" },					\
+	{ IFM_1000_T,	"1000baseTX" },					\
+	{ IFM_1000_T,	"1000baseT" },					\
+	{ IFM_HPNA_1,	"homePNA" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_ETHERNET_ALIASES {					\
+	{ IFM_10_T,	"UTP" },					\
+	{ IFM_10_T,	"10UTP" },					\
+	{ IFM_10_2,	"BNC" },					\
+	{ IFM_10_2,	"10BNC" },					\
+	{ IFM_10_5,	"AUI" },					\
+	{ IFM_10_5,	"10AUI" },					\
+	{ IFM_100_TX,	"100TX" },					\
+	{ IFM_100_T4,	"100T4" },					\
+	{ IFM_100_VG,	"100VG" },					\
+	{ IFM_100_T2,	"100T2" },					\
+	{ IFM_10_STP,	"10STP" },					\
+	{ IFM_10_FL,	"10FL" },					\
+	{ IFM_1000_SX,	"1000SX" },					\
+	{ IFM_1000_LX,	"1000LX" },					\
+	{ IFM_1000_CX,	"1000CX" },					\
+	{ IFM_1000_T,	"1000TX" },					\
+	{ IFM_1000_T,	"1000T" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS {			\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_TOKENRING_DESCRIPTIONS {				\
+	{ IFM_TOK_STP4,	"DB9/4Mbit" },					\
+	{ IFM_TOK_STP16, "DB9/16Mbit" },				\
+	{ IFM_TOK_UTP4,	"UTP/4Mbit" },					\
+	{ IFM_TOK_UTP16, "UTP/16Mbit" },				\
+	{ IFM_TOK_STP100, "STP/100Mbit" },				\
+	{ IFM_TOK_UTP100, "UTP/100Mbit" },				\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_TOKENRING_ALIASES {					\
+	{ IFM_TOK_STP4,	"4STP" },					\
+	{ IFM_TOK_STP16, "16STP" },					\
+	{ IFM_TOK_UTP4,	"4UTP" },					\
+	{ IFM_TOK_UTP16, "16UTP" },					\
+	{ IFM_TOK_STP100, "100STP" },					\
+	{ IFM_TOK_UTP100, "100UTP" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS {			\
+	{ IFM_TOK_ETR,	"EarlyTokenRelease" },				\
+	{ IFM_TOK_SRCRT, "SourceRouting" },				\
+	{ IFM_TOK_ALLR,	 "AllRoutes" },					\
+	{ IFM_TOK_DTR,	 "Dedicated" },					\
+	{ IFM_TOK_CLASSIC, "Classic" },					\
+	{ IFM_TOK_AUTO,	" " },						\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_FDDI_DESCRIPTIONS {					\
+	{ IFM_FDDI_SMF, "Single-mode" },				\
+	{ IFM_FDDI_MMF, "Multi-mode" },					\
+	{ IFM_FDDI_UTP, "UTP" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_FDDI_ALIASES {					\
+	{ IFM_FDDI_SMF,	"SMF" },					\
+	{ IFM_FDDI_MMF,	"MMF" },					\
+	{ IFM_FDDI_UTP,	"CDDI" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS {				\
+	{ IFM_FDDI_DA, "Dual-attach" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_IEEE80211_DESCRIPTIONS {				\
+	{ IFM_IEEE80211_FH1, "FH/1Mbps" },				\
+	{ IFM_IEEE80211_FH2, "FH/2Mbps" },				\
+	{ IFM_IEEE80211_DS1, "DS/1Mbps" },				\
+	{ IFM_IEEE80211_DS2, "DS/2Mbps" },				\
+	{ IFM_IEEE80211_DS5, "DS/5.5Mbps" },				\
+	{ IFM_IEEE80211_DS11, "DS/11Mbps" },				\
+	{ IFM_IEEE80211_DS22, "DS/22Mbps" },				\
+	{ IFM_IEEE80211_OFDM1_50, "OFDM/1.50Mbps" },			\
+	{ IFM_IEEE80211_OFDM2_25, "OFDM/2.25Mbps" },			\
+	{ IFM_IEEE80211_OFDM3, "OFDM/3Mbps" },				\
+	{ IFM_IEEE80211_OFDM4_50, "OFDM/4.5Mbps" },			\
+	{ IFM_IEEE80211_OFDM6, "OFDM/6Mbps" },				\
+	{ IFM_IEEE80211_OFDM9, "OFDM/9Mbps" },				\
+	{ IFM_IEEE80211_OFDM12, "OFDM/12Mbps" },			\
+	{ IFM_IEEE80211_OFDM13_5, "OFDM/13.5Mbps" },			\
+	{ IFM_IEEE80211_OFDM18, "OFDM/18Mbps" },			\
+	{ IFM_IEEE80211_OFDM24, "OFDM/24Mbps" },			\
+	{ IFM_IEEE80211_OFDM27, "OFDM/27Mbps" },			\
+	{ IFM_IEEE80211_OFDM36, "OFDM/36Mbps" },			\
+	{ IFM_IEEE80211_OFDM48, "OFDM/48Mbps" },			\
+	{ IFM_IEEE80211_OFDM54, "OFDM/54Mbps" },			\
+	{ IFM_IEEE80211_OFDM72, "OFDM/72Mbps" },			\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_IEEE80211_ALIASES {					\
+	{ IFM_IEEE80211_FH1, "FH1" },					\
+	{ IFM_IEEE80211_FH2, "FH2" },					\
+	{ IFM_IEEE80211_FH1, "FrequencyHopping/1Mbps" },		\
+	{ IFM_IEEE80211_FH2, "FrequencyHopping/2Mbps" },		\
+	{ IFM_IEEE80211_DS1, "DS1" },					\
+	{ IFM_IEEE80211_DS2, "DS2" },					\
+	{ IFM_IEEE80211_DS5, "DS5.5" },					\
+	{ IFM_IEEE80211_DS11, "DS11" },					\
+	{ IFM_IEEE80211_DS22, "DS22" },					\
+	{ IFM_IEEE80211_DS1, "DirectSequence/1Mbps" },			\
+	{ IFM_IEEE80211_DS2, "DirectSequence/2Mbps" },			\
+	{ IFM_IEEE80211_DS5, "DirectSequence/5.5Mbps" },		\
+	{ IFM_IEEE80211_DS11, "DirectSequence/11Mbps" },		\
+	{ IFM_IEEE80211_DS22, "DirectSequence/22Mbps" },		\
+	{ IFM_IEEE80211_OFDM1_50, "OFDM1.50Mpbs" },			\
+	{ IFM_IEEE80211_OFDM2_25, "OFDM2.25Mbps" },			\
+	{ IFM_IEEE80211_OFDM3, "OFDM3Mbps" },				\
+	{ IFM_IEEE80211_OFDM4_50, "OFDM4.5Mbps" },			\
+	{ IFM_IEEE80211_OFDM6, "OFDM6" },				\
+	{ IFM_IEEE80211_OFDM9, "OFDM9" },				\
+	{ IFM_IEEE80211_OFDM12, "OFDM12" },				\
+	{ IFM_IEEE80211_OFDM13_5, "OFDM13.5Mbps" },			\
+	{ IFM_IEEE80211_OFDM18, "OFDM18" },				\
+	{ IFM_IEEE80211_OFDM24, "OFDM24" },				\
+	{ IFM_IEEE80211_OFDM27, "OFDM27" },				\
+	{ IFM_IEEE80211_OFDM36, "OFDM36" },				\
+	{ IFM_IEEE80211_OFDM48, "OFDM48" },				\
+	{ IFM_IEEE80211_OFDM54, "OFDM54" },				\
+	{ IFM_IEEE80211_OFDM72, "OFDM72" },				\
+	{ IFM_IEEE80211_DS1, "CCK1" },					\
+	{ IFM_IEEE80211_DS2, "CCK2" },					\
+	{ IFM_IEEE80211_DS5, "CCK5.5" },				\
+	{ IFM_IEEE80211_DS11, "CCK11" },				\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS {			\
+	{ IFM_IEEE80211_ADHOC, "adhoc" },				\
+	{ IFM_IEEE80211_HOSTAP, "hostap" },				\
+	{ IFM_IEEE80211_IBSS, "ibss" },					\
+	{ IFM_IEEE80211_WDS, "wds" },					\
+	{ IFM_IEEE80211_TURBO, "turbo" },				\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS {			\
+	{ IFM_IEEE80211_11A, "11a" },					\
+	{ IFM_IEEE80211_11B, "11b" },					\
+	{ IFM_IEEE80211_11G, "11g" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_SHARED_DESCRIPTIONS {				\
+	{ IFM_AUTO,	"autoselect" },					\
+	{ IFM_MANUAL,	"manual" },					\
+	{ IFM_NONE,	"none" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SUBTYPE_SHARED_ALIASES {					\
+	{ IFM_AUTO,	"auto" },					\
+	{ 0, NULL },							\
+}
+
+#define	IFM_SHARED_OPTION_DESCRIPTIONS {				\
+	{ IFM_FDX,	"full-duplex" },				\
+	{ IFM_HDX,	"half-duplex" },				\
+	{ IFM_FLAG0,	"flag0" },					\
+	{ IFM_FLAG1,	"flag1" },					\
+	{ IFM_FLAG2,	"flag2" },					\
+	{ IFM_LOOP,	"hw-loopback" },				\
+	{ 0, NULL },							\
+}
+
+#endif	/* _NET_IF_MEDIA_H_ */
diff -Nur kamikaze_7.09.orig/package/madwifi/Makefile kamikaze_7.09/package/madwifi/Makefile
--- kamikaze_7.09.orig/package/madwifi/Makefile	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -1,27 +1,42 @@
 # 
-# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2006-2008 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
 #
-# $Id: Makefile 8682 2007-09-07 20:57:08Z nbd $
+# $Id: Makefile 11352 2008-06-04 13:51:17Z kaloz $
 
 include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=madwifi
-PKG_VERSION:=r2568-20070710
-PKG_BRANCH:=madwifi-ng
-PKG_RELEASE:=2
-
-PKG_SOURCE:=$(PKG_BRANCH)-$(PKG_VERSION).tar.gz
-PKG_SOURCE_URL:=http://snapshots.madwifi.org/$(PKG_BRANCH)
-PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_BRANCH)-$(PKG_VERSION)
-PKG_MD5SUM:=fe5d41acd085d2c46934be3f8839e694
+PKG_REV:=3314
+PKG_VERSION:=r$(PKG_REV)
+# PKG_BRANCH:=madwifi-dfs
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=svn
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_SUBDIR:=$(if $(PKG_BRANCH),$(PKG_BRANCH),madwifi-trunk)-$(PKG_VERSION)
+PKG_SOURCE_URL:=http://svn.madwifi.org/madwifi/$(if $(PKG_BRANCH),branches/$(PKG_BRANCH),trunk)
+PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(PKG_BRANCH),$(PKG_BRANCH),madwifi-trunk)-$(PKG_VERSION)
 
 include $(INCLUDE_DIR)/package.mk
 
-RATE_CONTROL:=minstrel
+ifneq ($(CONFIG_TARGET_atheros),)
+  BUS:=AHB
+else
+  ifneq ($(CONFIG_PCI_SUPPORT),)
+    BUS:=PCI
+  endif
+endif
+
+# XXX: remove this check later when we have PCI support properly detected on all targets
+ifneq ($(CONFIG_TARGET_ar7)$(CONFIG_TARGET_uml),)
+  BUS:=
+endif
 
 ifeq ($(ARCH),mips)
   HAL_TARGET:=mips-be-elf
@@ -32,30 +47,58 @@
 ifeq ($(ARCH),i386)
   HAL_TARGET:=i386-elf
 endif
-ifeq ($(ARCH),armeb)
+ifeq ($(ARCH),i686)
+  HAL_TARGET:=i386-elf
+endif
+ifeq ($(BOARD),ixp4xx)
   HAL_TARGET:=xscale-be-elf
 endif
-ifeq ($(ARCH),arm)
+ifeq ($(BOARD),iop32x)
+  HAL_TARGET:=xscale-le-elf
+endif
+ifeq ($(BOARD),orion)
   HAL_TARGET:=xscale-le-elf
 endif
 ifeq ($(ARCH),powerpc)
   HAL_TARGET:=powerpc-be-elf
 endif
+ifeq ($(BOARD),storm)
+  HAL_TARGET:=armv4-le-elf
+endif
+ifneq ($(CONFIG_TARGET_atheros),)
+  HAL_TARGET:=wisoc
+endif
 
-BUS:=PCI
-ifneq ($(CONFIG_LINUX_2_6_ATHEROS),)
-  BUS:=AHB
-  HAL_TARGET:=ap51
+RATE_CONTROL:=minstrel
+
+ifdef CONFIG_MADWIFI_RCA_MINSTREL
+  RATE_CONTROL:=minstrel
 endif
 
-BUS_MODULES:=
-ifeq ($(findstring AHB,$(BUS)),AHB)
-  BUS_MODULES+=$(PKG_BUILD_DIR)/ath/ath_ahb.$(LINUX_KMOD_SUFFIX)
+ifdef CONFIG_MADWIFI_RCA_ONOE
+  RATE_CONTROL:=onoe
 endif
-ifeq ($(findstring PCI,$(BUS)),PCI)
-  BUS_MODULES+=$(PKG_BUILD_DIR)/ath/ath_pci.$(LINUX_KMOD_SUFFIX)
+
+ifdef CONFIG_MADWIFI_RCA_AMRR
+  RATE_CONTROL:=amrr
+endif
+
+ifdef CONFIG_MADWIFI_RCA_SAMPLERATE
+  RATE_CONTROL:=sample
 endif
 
+MADWIFI_FILES:= \
+	$(PKG_BUILD_DIR)/net80211/wlan.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_scan_ap.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_scan_sta.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/ath_hal/ath_hal.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_acl.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_ccmp.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_tkip.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_wep.$(LINUX_KMOD_SUFFIX) \
+	$(PKG_BUILD_DIR)/net80211/wlan_xauth.$(LINUX_KMOD_SUFFIX) \
+
 MADWIFI_AUTOLOAD:= \
 	wlan \
 	wlan_scan_ap \
@@ -66,26 +109,29 @@
 	wlan_ccmp \
 	wlan_tkip \
 	wlan_wep \
-	wlan_xauth
+	wlan_xauth \
 
 ifeq ($(findstring AHB,$(BUS)),AHB)
-	MADWIFI_AUTOLOAD += ath_ahb
+  MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_ahb.$(LINUX_KMOD_SUFFIX)
+  MADWIFI_AUTOLOAD+= ath_ahb/countrycode=40/outdoor=1/tpc=1
 endif
 ifeq ($(findstring PCI,$(BUS)),PCI)
-	MADWIFI_AUTOLOAD += ath_pci
+  MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_pci.$(LINUX_KMOD_SUFFIX)
+  MADWIFI_AUTOLOAD+= ath_pci/countrycode=40/outdoor=1/tpc=1
+endif
+
+MADWIFI_APPLETS:=80211stats,athchans,athctrl,athkey,athstats,wlanconfig
+ifdef CONFIG_MADWIFI_DEBUG
+  MADWIFI_APPLETS:=$(strip $(MADWIFI_APPLETS)),athdebug,80211debug
 endif
 
+
 define KernelPackage/madwifi
   SUBMENU:=Wireless Drivers
   TITLE:=Driver for Atheros wireless chipsets
-  DEPENDS:=+wireless-tools @!LINUX_2_6_AVR32
   URL:=http://madwifi.org/
-  VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
-  FILES:= \
-		$(PKG_BUILD_DIR)/ath_hal/ath_hal.$(LINUX_KMOD_SUFFIX) \
-		$(BUS_MODULES) \
-		$(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).$(LINUX_KMOD_SUFFIX) \
-		$(PKG_BUILD_DIR)/net80211/wlan*.$(LINUX_KMOD_SUFFIX)
+  DEPENDS:=+wireless-tools @PCI_SUPPORT||TARGET_atheros @!TARGET_ar7 @!TARGET_avr32 @!TARGET_etrax @!TARGET_uml
+  FILES:=$(MADWIFI_FILES)
   AUTOLOAD:=$(call AutoLoad,50,$(MADWIFI_AUTOLOAD))
 endef
 
@@ -93,28 +139,57 @@
  This package contains a driver for Atheros 802.11a/b/g chipsets.
 endef
 
-MADWIFI_MAKEOPTS= -C $(PKG_BUILD_DIR) \
-		PATH="$(TARGET_PATH)" \
-		ARCH="$(LINUX_KARCH)" \
-		CROSS_COMPILE="$(TARGET_CROSS)" \
-		TARGET="$(HAL_TARGET)" \
-		TOOLPREFIX="$(KERNEL_CROSS)" \
-		TOOLPATH="$(KERNEL_CROSS)" \
-		KERNELPATH="$(LINUX_DIR)" \
-		LDOPTS="--no-warn-mismatch " \
-		ATH_RATE="ath_rate/$(RATE_CONTROL)" \
-		WARNINGS="" \
-		DOMULTI=1
+define KernelPackage/madwifi/config
+	source "$(SOURCE)/Config.in"
+endef
+
+MAKE_ARGS:= \
+	PATH="$(TARGET_PATH)" \
+	ARCH="$(LINUX_KARCH)" \
+	CROSS_COMPILE="$(TARGET_CROSS)" \
+	TARGET="$(HAL_TARGET)" \
+	TOOLPREFIX="$(KERNEL_CROSS)" \
+	TOOLPATH="$(KERNEL_CROSS)" \
+	KERNELPATH="$(LINUX_DIR)" \
+	LDOPTS="--no-warn-mismatch " \
+	ATH_RATE="ath_rate/$(RATE_CONTROL)" \
+	WARNINGS="-Wno-unused" \
+	$(if $(CONFIG_MADWIFI_DEBUG),,DEBUG="") \
+	DO_MULTI=1
+
+MAKE_VARS:= \
+	COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"' -DATH_REVERSE_ENGINEERING=1" \
+
+HALFILE:=$(lastword $(sort $(wildcard ./ath_hal-*.tgz)))
+ifneq ($(HALFILE),)
+  define Build/Prepare
+	$(call Build/Prepare/Default)
+	rm -rf $(PKG_BUILD_DIR)/tmp
+	mkdir -p $(PKG_BUILD_DIR)/tmp
+	tar xvzf $(HALFILE) -C $(PKG_BUILD_DIR)/tmp
+	$(CP) $(PKG_BUILD_DIR)/tmp/ath_hal*/* $(PKG_BUILD_DIR)/hal/
+	rm -rf $(PKG_BUILD_DIR)/tmp
+	# patch cflags
+	$(SED) 's, -E[LB],,' \
+		-e 's, -mips2,,' \
+		-e 's, -mapcs-32,,' \
+		$(PKG_BUILD_DIR)/hal/public/*.inc
+	$(SED) 's,march=armv4,march=armv5te,' \
+		$(PKG_BUILD_DIR)/hal/public/xscale*.inc
+  endef
+endif
 
 ifeq ($(findstring AHB,$(BUS)),AHB)
   define Build/Compile/ahb
-	COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"'" $(MAKE) $(MADWIFI_MAKEOPTS) BUS="AHB" modules
+	$(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) BUS="AHB" modules
+	$(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) CFLAGS="$(TARGET_CFLAGS)" tools
   endef
 endif
 
 ifeq ($(findstring PCI,$(BUS)),PCI)
   define Build/Compile/pci
-	COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"'" $(MAKE) $(MADWIFI_MAKEOPTS) BUS="PCI" modules
+	$(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) BUS="PCI" modules
+	$(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) CFLAGS="$(TARGET_CFLAGS)" tools
   endef
 endif
 
@@ -125,27 +200,20 @@
 define Build/Compile
 	$(call Build/Compile/ahb)
 	$(call Build/Compile/pci)
-	$(MAKE) $(MADWIFI_MAKEOPTS) \
-		CFLAGS="$(TARGET_CFLAGS)" \
-		tools
 endef
 
 define Build/InstallDev
-	mkdir -p $(STAGING_DIR)/usr/include/madwifi
-	$(CP) $(PKG_BUILD_DIR)/include $(STAGING_DIR)/usr/include/madwifi/
-	mkdir -p $(STAGING_DIR)/usr/include/madwifi/net80211
-	$(CP) $(PKG_BUILD_DIR)/net80211/*.h $(STAGING_DIR)/usr/include/madwifi/net80211/
-endef
-
-define Build/UninstallDev
-	rm -rf	$(STAGING_DIR)/usr/include/madwifi
+	mkdir -p $(1)/usr/include/madwifi
+	$(CP) $(PKG_BUILD_DIR)/include $(1)/usr/include/madwifi/
+	mkdir -p $(1)/usr/include/madwifi/net80211
+	$(CP) $(PKG_BUILD_DIR)/net80211/*.h $(1)/usr/include/madwifi/net80211/
 endef
 
 define KernelPackage/madwifi/install
 	$(INSTALL_DIR) $(1)/lib/wifi
 	$(INSTALL_DATA) ./files/lib/wifi/madwifi.sh $(1)/lib/wifi
 	$(INSTALL_DIR) $(1)/usr/sbin
-	$(CP) $(PKG_BUILD_DIR)/tools/{madwifi_multi,80211stats,athchans,athctrl,athkey,athstats,wlanconfig} $(1)/usr/sbin/
+	$(CP) $(PKG_BUILD_DIR)/tools/{madwifi_multi,$(MADWIFI_APPLETS)} $(1)/usr/sbin/
 endef
 
 $(eval $(call KernelPackage,madwifi))
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/100-kernel_cflags.patch kamikaze_7.09/package/madwifi/patches/100-kernel_cflags.patch
--- kamikaze_7.09.orig/package/madwifi/patches/100-kernel_cflags.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/100-kernel_cflags.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,33 +0,0 @@
-Index: madwifi-ng-r2568-20070710/hal/public/mips-be-elf.inc
-===================================================================
---- madwifi-ng-r2568-20070710.orig/hal/public/mips-be-elf.inc	2007-07-23 01:48:38.974201182 +0200
-+++ madwifi-ng-r2568-20070710/hal/public/mips-be-elf.inc	2007-07-23 01:48:39.166212125 +0200
-@@ -71,5 +71,5 @@
- 
- LDOPTS=	-EB
- COPTS+=	-DAH_BYTE_ORDER=AH_BIG_ENDIAN
--COPTS+=	-G 0 -EB -mno-abicalls -fno-pic -mips2 -Wa,--trap \
-+COPTS+=	-G 0 -mno-abicalls -fno-pic -mips32 -Wa,--trap \
- 	-fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls
-Index: madwifi-ng-r2568-20070710/hal/public/mips-le-elf.inc
-===================================================================
---- madwifi-ng-r2568-20070710.orig/hal/public/mips-le-elf.inc	2007-07-23 01:48:38.982201640 +0200
-+++ madwifi-ng-r2568-20070710/hal/public/mips-le-elf.inc	2007-07-23 01:48:39.170212355 +0200
-@@ -68,5 +68,5 @@
- 
- LDOPTS=	-EL
- COPTS+=	-DAH_BYTE_ORDER=AH_LITTLE_ENDIAN
--COPTS+=	-G 0 -EL -mno-abicalls -fno-pic -mips2 -Wa,--trap \
-+COPTS+=	-G 0 -mno-abicalls -fno-pic -mips32 -Wa,--trap \
- 	-fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls
-Index: madwifi-ng-r2568-20070710/hal/public/xscale-be-elf.inc
-===================================================================
---- madwifi-ng-r2568-20070710.orig/hal/public/xscale-be-elf.inc	2007-07-23 01:48:38.990202093 +0200
-+++ madwifi-ng-r2568-20070710/hal/public/xscale-be-elf.inc	2007-07-23 01:48:39.194213721 +0200
-@@ -77,5 +77,5 @@
- 
- LDOPTS=	-EB
- COPTS+=	-DAH_BYTE_ORDER=AH_BIG_ENDIAN
--COPTS+= -march=armv4 -mbig-endian -fno-strict-aliasing -fno-common -mapcs-32 \
-+COPTS+= -march=armv5te -mbig-endian -fno-strict-aliasing -fno-common  \
- 	-mtune=xscale  -mshort-load-bytes
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/102-multicall_binary.patch kamikaze_7.09/package/madwifi/patches/102-multicall_binary.patch
--- kamikaze_7.09.orig/package/madwifi/patches/102-multicall_binary.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/102-multicall_binary.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,256 +1,142 @@
-Index: madwifi-ng-r2568-20070710/tools/80211debug.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/80211debug.c	2007-07-23 01:48:38.846193887 +0200
-+++ madwifi-ng-r2568-20070710/tools/80211debug.c	2007-07-23 01:48:39.578235605 +0200
-@@ -49,6 +49,10 @@
+--- a/tools/80211debug.c
++++ b/tools/80211debug.c
+@@ -48,6 +48,7 @@
+ #include <ctype.h>
  #include <getopt.h>
  #include <err.h>
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
- #define	N(a)	(sizeof(a)/sizeof(a[0]))
  
- const char *progname;
-@@ -180,9 +184,19 @@
- }
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -185,7 +186,7 @@
  #endif /* __linux__ */
  
-+#ifdef DOMULTI
-+
-+int
-+a80211debug_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(a80211debug)(int argc, char *argv[])
  {
-+
-+#endif
  	const char *ifname = "ath0";
  	const char *cp, *tp;
- 	const char *sep;
-Index: madwifi-ng-r2568-20070710/tools/80211stats.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/80211stats.c	2007-07-23 01:48:38.854194346 +0200
-+++ madwifi-ng-r2568-20070710/tools/80211stats.c	2007-07-23 01:48:39.578235605 +0200
-@@ -60,6 +60,10 @@
+--- a/tools/80211stats.c
++++ b/tools/80211stats.c
+@@ -59,6 +59,7 @@
+ #include "net80211/ieee80211.h"
  #include "net80211/ieee80211_crypto.h"
  #include "net80211/ieee80211_ioctl.h"
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
+ 
  #ifndef SIOCG80211STATS
  #define	SIOCG80211STATS	(SIOCDEVPRIVATE + 2)
- #endif
-@@ -243,9 +247,19 @@
- #undef STAT
+@@ -240,7 +241,7 @@
  }
  
-+#ifdef DOMULTI
-+
-+int
-+a80211stats_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(a80211stats)(int argc, char *argv[])
  {
-+
-+#endif
  	int c, len;
  	struct ieee80211req_sta_info *si;
- 	u_int8_t buf[24*1024], *cp;
-Index: madwifi-ng-r2568-20070710/tools/athchans.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/athchans.c	2007-07-23 01:48:38.858194572 +0200
-+++ madwifi-ng-r2568-20070710/tools/athchans.c	2007-07-23 01:48:39.598236745 +0200
-@@ -59,6 +59,10 @@
+--- a/tools/athchans.c
++++ b/tools/athchans.c
+@@ -58,6 +58,7 @@
+ #include "net80211/ieee80211.h"
  #include "net80211/ieee80211_crypto.h"
  #include "net80211/ieee80211_ioctl.h"
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
- static	int s = -1;
- const char *progname;
  
-@@ -138,9 +142,20 @@
+ static	int s = -1;
+ static const char *progname;
+@@ -140,8 +141,9 @@
  }
  
  #define	MAXCHAN	((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
 +
-+#ifdef DOMULTI
-+
-+int
-+athchans_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(athchans)(int argc, char *argv[])
  {
-+
-+#endif
  	const char *ifname = "wifi0";
  	struct ieee80211req_chanlist chanlist;
- 	int c;
-Index: madwifi-ng-r2568-20070710/tools/athctrl.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/athctrl.c	2007-07-23 01:48:38.866195027 +0200
-+++ madwifi-ng-r2568-20070710/tools/athctrl.c	2007-07-23 01:48:39.626238340 +0200
-@@ -53,6 +53,10 @@
+--- a/tools/athctrl.c
++++ b/tools/athctrl.c
+@@ -52,6 +52,7 @@
+ #include <err.h>
  
  #include <net/if.h>
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
+ 
  static int
  setsysctrl(const char *dev, const char *control , u_long value)
- {
-@@ -87,9 +91,19 @@
- 	exit(1);
+@@ -88,7 +89,7 @@
  }
  
-+#ifdef DOMULTI
-+
-+int
-+athctrl_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(athctrl)(int argc, char *argv[])
  {
-+
-+#endif
  	char device[IFNAMSIZ + 1];
  	int distance = -1;
- 	int c;
-Index: madwifi-ng-r2568-20070710/tools/athdebug.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/athdebug.c	2007-07-23 01:48:38.874195486 +0200
-+++ madwifi-ng-r2568-20070710/tools/athdebug.c	2007-07-23 01:48:39.650239706 +0200
-@@ -52,6 +52,10 @@
+--- a/tools/athdebug.c
++++ b/tools/athdebug.c
+@@ -51,6 +51,7 @@
+ #include <ctype.h>
  #include <getopt.h>
  #include <err.h>
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
- #define	N(a)	(sizeof(a)/sizeof(a[0]))
  
- const char *progname;
-@@ -179,9 +183,20 @@
- }
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -194,7 +195,7 @@
  #endif /* __linux__ */
  
-+#ifdef DOMULTI
-+
-+int
-+athdebug_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(athdebug)(int argc, char *argv[])
  {
-+
-+#endif
-+
  #ifdef __linux__
  	const char *ifname = "wifi0";
- #else
-Index: madwifi-ng-r2568-20070710/tools/athkey.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/athkey.c	2007-07-23 01:48:38.878195712 +0200
-+++ madwifi-ng-r2568-20070710/tools/athkey.c	2007-07-23 01:48:39.698242443 +0200
-@@ -59,6 +59,10 @@
+--- a/tools/athkey.c
++++ b/tools/athkey.c
+@@ -58,6 +58,7 @@
+ #include "net80211/ieee80211.h"
  #include "net80211/ieee80211_crypto.h"
  #include "net80211/ieee80211_ioctl.h"
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
- static int s = -1;
- const char *progname;
  
-@@ -211,9 +215,19 @@
+ static int s = -1;
+ static const char *progname;
+@@ -213,8 +214,7 @@
  	exit(-1);
  }
  
-+#ifdef DOMULTI
-+
-+int
-+athkey_init(int argc, char *argv[])
-+{
-+
-+#else
-+
- int
- main(int argc, char *argv[])
+-int
+-main(int argc, char *argv[])
++int CMD(athkey)(int argc, char *argv[])
  {
-+
-+#endif
  	const char *ifname = "wifi0";
  	struct ieee80211req_key setkey;
- 	struct ieee80211req_del_key delkey;
-Index: madwifi-ng-r2568-20070710/tools/athstats.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/athstats.c	2007-07-23 01:48:38.886196167 +0200
-+++ madwifi-ng-r2568-20070710/tools/athstats.c	2007-07-23 01:48:39.726244040 +0200
-@@ -63,6 +63,10 @@
- #include "wireless_copy.h"
- #include "if_athioctl.h"
+--- a/tools/athstats.c
++++ b/tools/athstats.c
+@@ -65,6 +65,7 @@
  
-+#ifdef DOMULTI
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 +#include "do_multi.h"
-+#endif
-+
+ 
  static const struct {
  	u_int		phyerr;
- 	const char*	desc;
-@@ -226,9 +230,20 @@
- 	signalled = 1;
+@@ -228,7 +229,7 @@
  }
  
-+#ifdef DOMULTI
-+
-+int
-+athstats_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(athstats)(int argc, char *argv[])
  {
-+
-+#endif
-+
  #ifdef __linux__
  	const char *ifname = "wifi0";
- #else
-Index: madwifi-ng-r2568-20070710/tools/do_multi.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ madwifi-ng-r2568-20070710/tools/do_multi.c	2007-07-23 01:48:39.754245634 +0200
-@@ -0,0 +1,30 @@
+--- /dev/null
++++ b/tools/do_multi.c
+@@ -0,0 +1,32 @@
 +#include <string.h>
 +#include "do_multi.h"
 +
@@ -278,15 +164,15 @@
 +	ret =  athstats_init(argc, argv);
 +    if(strcmp(progname, "wlanconfig") == 0)
 +	ret =  wlanconfig_init(argc, argv);
++    if(strcmp(progname, "ath_info") == 0)
++	ret =  athinfo_init(argc, argv);
 +
 +    return ret;
 +}
-Index: madwifi-ng-r2568-20070710/tools/do_multi.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ madwifi-ng-r2568-20070710/tools/do_multi.h	2007-07-23 01:48:39.778247001 +0200
-@@ -0,0 +1,9 @@
-+
+--- /dev/null
++++ b/tools/do_multi.h
+@@ -0,0 +1,15 @@
++#ifdef DO_MULTI
 +int a80211debug_init(int argc, char *argv[]);
 +int a80211stats_init(int argc, char *argv[]);
 +int athchans_init(int argc, char *argv[]);
@@ -295,86 +181,134 @@
 +int athkey_init(int argc, char *argv[]);
 +int athstats_init(int argc, char *argv[]);
 +int wlanconfig_init(int argc, char *argv[]);
-Index: madwifi-ng-r2568-20070710/tools/Makefile
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/Makefile	2007-07-23 01:48:38.902197078 +0200
-+++ madwifi-ng-r2568-20070710/tools/Makefile	2007-07-23 01:48:39.798248141 +0200
-@@ -49,6 +49,12 @@
- 
- ALL=	athstats 80211stats athkey athchans athctrl \
- 	athdebug 80211debug wlanconfig
-+	
-+ifdef DOMULTI
-+OBJS=	do_multi.o athstats.o 80211stats.o athkey.o athchans.o athctrl.o \
-+	athdebug.o 80211debug.o wlanconfig.o
-+ALL=	${OBJS} madwifi_multi
++int athinfo_init(int argc, char *argv[]);
++
++#define CMD(name) name##_init
++#else
++#define CMD(name) main
++#endif
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -46,56 +46,55 @@
+ HAL=   $(TOP)/hal
+ endif
+ 
++all: compile
+ 
+-ALL=	athstats 80211stats athkey athchans athctrl \
++ALLPROGS=	athstats 80211stats athkey athchans athctrl \
+ 	athdebug 80211debug wlanconfig ath_info
+ 
+-all:	$(ALL)
++OBJS=	$(patsubst %,%.o,$(ALLPROGS))
+ 
+-INCS=	-I. -I$(HAL) -I$(TOP) -I$(ATH_HAL)
++INCS=	-I. -I../ath -I$(HAL) -I$(TOP) -I$(ATH_HAL)
+ CFLAGS=	-g -O2 -Wall
+ ALL_CFLAGS= $(CFLAGS) $(INCS)
+ LDFLAGS=
+ 
+-all:	$(ALL)
+ 
+-athstats: athstats.c
+-	$(CC) -o athstats $(ALL_CFLAGS) -I$(TOP)/ath $(LDFLAGS) athstats.c
+-80211stats: 80211stats.c
+-	$(CC) -o 80211stats $(ALL_CFLAGS) $(LDFLAGS) 80211stats.c
+-athkey: athkey.c
+-	$(CC) -o athkey $(ALL_CFLAGS) $(LDFLAGS) athkey.c
+-athchans: athchans.c
+-	$(CC) -o athchans $(ALL_CFLAGS) $(LDFLAGS) athchans.c
+-athctrl: athctrl.c
+-	$(CC) -o athctrl $(ALL_CFLAGS) $(LDFLAGS) athctrl.c
+-athdebug: athdebug.c
+-	$(CC) -o athdebug $(ALL_CFLAGS) $(LDFLAGS) athdebug.c
+-wlanconfig: wlanconfig.c
+-	$(CC) -o wlanconfig $(ALL_CFLAGS) $(LDFLAGS) wlanconfig.c
+-80211debug: 80211debug.c
+-	$(CC) -o 80211debug $(ALL_CFLAGS) $(LDFLAGS) 80211debug.c
+-ath_info: ath_info.c
+-	$(CC) -o ath_info $(CFLAGS) ath_info.c
++ifneq ($(DO_MULTI),)
++ALL_CFLAGS += -DDO_MULTI=1
++%.o: %.c
++	${CC} $(ALL_CFLAGS) -c -o $@  $<
++
++madwifi_multi: $(OBJS) do_multi.o
++	$(CC) -o $@ $^
++
++compile: madwifi_multi
++	for i in $(ALLPROGS); do \
++		ln -s -f madwifi_multi $$i; \
++	done
++else
++$(ALLPROGS):
++	$(CC) $(ALL_CFLAGS) -o $@ $@.c
++
++compile: $(ALLPROGS)
 +endif
  
- all:	$(ALL)
- 
-@@ -59,6 +65,30 @@
- 
- all:	$(ALL)
  
-+athstats.o: athstats.c
-+	${CC} -c -o athstats.o -DDOMULTI=1 ${ALL_CFLAGS} -I../ath athstats.c
-+80211stats.o: 80211stats.c
-+	${CC} -c -o 80211stats.o -DDOMULTI=1 ${ALL_CFLAGS} 80211stats.c
-+athkey.o: athkey.c
-+	${CC} -c -o athkey.o -DDOMULTI=1 ${ALL_CFLAGS} athkey.c
-+athchans.o: athchans.c
-+	${CC} -c -o athchans.o -DDOMULTI=1 ${ALL_CFLAGS} athchans.c
-+athctrl.o: athctrl.c
-+	${CC} -c -o athctrl.o -DDOMULTI=1 ${ALL_CFLAGS} athctrl.c
-+athdebug.o: athdebug.c
-+	${CC} -c -o athdebug.o -DDOMULTI=1 ${ALL_CFLAGS} athdebug.c
-+wlanconfig.o: wlanconfig.c
-+	${CC} -c -o wlanconfig.o -DDOMULTI=1 ${ALL_CFLAGS} wlanconfig.c
-+80211debug.o: 80211debug.c
-+	${CC} -c -o 80211debug.o -DDOMULTI=1 ${ALL_CFLAGS} 80211debug.c
-+do_multi.o: do_multi.c
-+	${CC} -c -o do_multi.o -DDOMULTI=1 ${ALL_CFLAGS} do_multi.c
-+madwifi_multi:
-+	${CC} -o madwifi_multi ${LDFLAGS} ${OBJS}
-+	for i in athstats 80211stats athkey athchans athctrl athdebug wlanconfig 80211debug; do \
-+	ln -s -f madwifi_multi $$i; \
-+	done
-+
- athstats: athstats.c
- 	$(CC) -o athstats $(ALL_CFLAGS) -I$(TOP)/ath $(LDFLAGS) athstats.c
- 80211stats: 80211stats.c
-Index: madwifi-ng-r2568-20070710/tools/wlanconfig.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/wlanconfig.c	2007-07-23 01:48:38.910197536 +0200
-+++ madwifi-ng-r2568-20070710/tools/wlanconfig.c	2007-07-23 01:48:39.850251108 +0200
-@@ -62,6 +62,10 @@
+ install: $(ALL) 
+ 	install -d $(DESTDIR)$(BINDIR)
+-	for i in $(ALL); do \
++	for i in $(ALLPROGS) $(if $(DO_MULTI),madwifi_multi); do \
+ 		install $$i $(DESTDIR)$(BINDIR)/$$i; \
+-		$(STRIP) $(DESTDIR)$(BINDIR)/$$i; \
+ 	done
+ 	install -d $(DESTDIR)$(MANDIR)/man8
+ 	install -m 0644 man/*.8 $(DESTDIR)$(MANDIR)/man8
+ 	install $(TOP)/scripts/madwifi-unload $(DESTDIR)$(BINDIR)/madwifi-unload
+ 
+ uninstall:
+-	for i in $(ALL); do \
++	for i in $(ALLPROGS) $(if $(DO_MULTI),madwifi_multi); do \
+ 		rm -f $(DESTDIR)$(BINDIR)/$$i; \
+ 	done
+-	for i in $(ALL:=.8); do \
+-		rm -f $(DESTDIR)$(MANDIR)/man8/$$i; \
++	for i in $(ALLPROGS); do \
++		rm -f $(DESTDIR)$(MANDIR)/man8/$$i.8; \
+ 	done
+ 
+ clean:
+-	rm -f $(ALL) core a.out
++	rm -f $(ALLPROGS) madwifi_multi *.o core a.out
+--- a/tools/wlanconfig.c
++++ b/tools/wlanconfig.c
+@@ -61,6 +61,7 @@
+ #include "net80211/ieee80211.h"
  #include "net80211/ieee80211_crypto.h"
  #include "net80211/ieee80211_ioctl.h"
- 
-+#ifdef DOMULTI
 +#include "do_multi.h"
-+#endif
-+
+ 
  /*
   * These are taken from ieee80211_node.h
-  */
-@@ -96,9 +100,19 @@
- 
- int verbose = 0;
+@@ -100,7 +101,7 @@
+ static int verbose = 0;
  
-+#ifdef DOMULTI
-+
-+int
-+wlanconfig_init(int argc, char *argv[])
-+{
-+
-+#else
-+
  int
- main(int argc, char *argv[])
+-main(int argc, char *argv[])
++CMD(wlanconfig)(int argc, char *argv[])
  {
-+
-+#endif
  	const char *ifname, *cmd;
  	unsigned char bnounit = 0;
- 	char *if_base = NULL;
+--- a/tools/ath_info.c
++++ b/tools/ath_info.c
+@@ -98,6 +98,7 @@
+ #include <sys/mman.h>
+ #include <endian.h>
+ #include <byteswap.h>
++#include "do_multi.h"
+ 
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -738,7 +739,8 @@
+ 		"unlawful radio transmissions!\n\n");
+ }
+ 
+-int main(int argc, char *argv[])
++int
++CMD(athinfo)(int argc, char *argv[])
+ {
+ 	u_int32_t dev_addr;
+ 	u_int16_t eeprom_header, srev, phy_rev_5ghz, phy_rev_2ghz;
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/104-autocreate_none.patch kamikaze_7.09/package/madwifi/patches/104-autocreate_none.patch
--- kamikaze_7.09.orig/package/madwifi/patches/104-autocreate_none.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/104-autocreate_none.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,8 +1,6 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:38.770189557 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:40.226272533 +0200
-@@ -427,7 +427,7 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -516,7 +516,7 @@
  	HAL_STATUS status;
  	int error = 0;
  	unsigned int i;
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/105-ratectl_attach.patch kamikaze_7.09/package/madwifi/patches/105-ratectl_attach.patch
--- kamikaze_7.09.orig/package/madwifi/patches/105-ratectl_attach.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/105-ratectl_attach.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,7 +1,5 @@
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_rate.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_rate.c	2007-07-23 01:48:38.694185224 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_rate.c	2007-07-23 01:48:40.474286668 +0200
+--- a/net80211/ieee80211_rate.c
++++ b/net80211/ieee80211_rate.c
 @@ -100,8 +100,18 @@
  		ieee80211_load_module(buf);
  
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/110-init_fix_PR_914.patch kamikaze_7.09/package/madwifi/patches/110-init_fix_PR_914.patch
--- kamikaze_7.09.orig/package/madwifi/patches/110-init_fix_PR_914.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/110-init_fix_PR_914.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,15 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:40.226272533 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:40.726301028 +0200
-@@ -1988,7 +1988,10 @@
- 		ath_draintxq(sc);
- 		if (!sc->sc_invalid) {
- 			ath_stoprecv(sc);
-+
-+			/* XXX: this helps to avoid crashes on ifconfig down/up
- 			ath_hal_phydisable(ah);
-+			 */
- 		} else
- 			sc->sc_rxlink = NULL;
- 		ath_beacon_free(sc);		/* XXX needed? */
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/111-minstrel_crash.patch kamikaze_7.09/package/madwifi/patches/111-minstrel_crash.patch
--- kamikaze_7.09.orig/package/madwifi/patches/111-minstrel_crash.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/111-minstrel_crash.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,8 +1,6 @@
-Index: madwifi-ng-r2568-20070710/ath_rate/minstrel/minstrel.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath_rate/minstrel/minstrel.c	2007-07-23 01:48:38.542176563 +0200
-+++ madwifi-ng-r2568-20070710/ath_rate/minstrel/minstrel.c	2007-07-23 01:48:40.974315165 +0200
-@@ -388,6 +388,9 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -393,6 +393,9 @@
  		struct minstrel_node *sn = ATH_NODE_MINSTREL(an);
  		int rc1, rc2, rc3;         /* Index into the rate table, so for example, it is  0..11 */
  
@@ -10,5 +8,5 @@
 +			return;
 +
  		if (sn->is_sampling) {
- 			rc1 = sn->max_tp_rate;
  			sn->is_sampling = 0;
+ 			if (sn->rs_sample_rate_slower)
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/112-keycache_PR_962.patch kamikaze_7.09/package/madwifi/patches/112-keycache_PR_962.patch
--- kamikaze_7.09.orig/package/madwifi/patches/112-keycache_PR_962.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/112-keycache_PR_962.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,61 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:40.726301028 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:41.230329754 +0200
-@@ -5732,7 +5732,8 @@
- 		 * frame; it'll be dropped where it's not wanted.
- 		 */
- 		if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
--		    (ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
-+		    ((ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) &&
-+			ieee80211_check_rxnode(ni, (const struct ieee80211_frame_min *) skb->data)) {
- 			struct ath_node *an;
- 			/*
- 			 * Fast path: node is present in the key map;
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_node.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_node.c	2007-07-23 01:48:38.458171774 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_node.c	2007-07-23 01:48:41.230329754 +0200
-@@ -1271,8 +1271,6 @@
- 	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
- 
- 	return ni;
--#undef IS_PSPOLL
--#undef IS_CTL
- }
- #ifdef IEEE80211_DEBUG_REFCNT
- EXPORT_SYMBOL(ieee80211_find_rxnode_debug);
-@@ -1280,6 +1278,20 @@
- EXPORT_SYMBOL(ieee80211_find_rxnode);
- #endif
- 
-+int
-+ieee80211_check_rxnode(struct ieee80211_node *ni,
-+	const struct ieee80211_frame_min *wh)
-+{
-+	if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
-+		return IEEE80211_ADDR_EQ(ni->ni_macaddr, wh->i_addr1);
-+	else
-+		return IEEE80211_ADDR_EQ(ni->ni_macaddr, wh->i_addr2);
-+}
-+
-+EXPORT_SYMBOL(ieee80211_check_rxnode);
-+#undef IS_PSPOLL
-+#undef IS_CTL
-+
- /*
-  * Return a reference to the appropriate node for sending
-  * a data frame.  This handles node discovery in adhoc networks.
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_node.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_node.h	2007-07-23 01:48:38.466172232 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_node.h	2007-07-23 01:48:41.254331120 +0200
-@@ -328,6 +328,8 @@
- 	*pni = NULL;			/* guard against use */
- }
- 
-+int ieee80211_check_rxnode(struct ieee80211_node *ni,
-+	const struct ieee80211_frame_min *wh);
- int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *,
- 	const u_int8_t *, u_int8_t);
- void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/113-no_ibss_pwrsave.patch kamikaze_7.09/package/madwifi/patches/113-no_ibss_pwrsave.patch
--- kamikaze_7.09.orig/package/madwifi/patches/113-no_ibss_pwrsave.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/113-no_ibss_pwrsave.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,7 +1,5 @@
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_scan.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_scan.c	2007-07-23 01:48:38.374166989 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_scan.c	2007-07-23 01:48:41.534347075 +0200
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
 @@ -291,7 +291,8 @@
  	struct ieee80211com *ic = vap->iv_ic;
  	int delay;
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/116-adhoc_beacon_PR_1033.patch kamikaze_7.09/package/madwifi/patches/116-adhoc_beacon_PR_1033.patch
--- kamikaze_7.09.orig/package/madwifi/patches/116-adhoc_beacon_PR_1033.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/116-adhoc_beacon_PR_1033.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,197 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:41.230329754 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:41.758359843 +0200
-@@ -4426,16 +4426,31 @@
- 	struct ieee80211com *ic = &sc->sc_ic;
- 	struct ath_hal *ah = sc->sc_ah;
- 	struct ieee80211_node *ni;
--	u_int32_t nexttbtt, intval;
-+	u_int32_t nexttbtt = 0;
-+	u_int32_t intval;
-+	u_int64_t tsf, hw_tsf;
-+	u_int32_t tsftu, hw_tsftu;
-+	int should_reset_tsf = 0;
- 
- 	if (vap == NULL)
- 		vap = TAILQ_FIRST(&ic->ic_vaps);   /* XXX */
- 
- 	ni = vap->iv_bss;
- 
--	/* extract tstamp from last beacon and convert to TU */
--	nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4),
--			     LE_READ_4(ni->ni_tstamp.data));
-+	hw_tsf = ath_hal_gettsf64(ah);
-+	tsf = le64_to_cpu(ni->ni_tstamp.tsf);
-+	hw_tsftu = hw_tsf >> 10;
-+	tsftu = tsf >> 10;
-+
-+	/* we should reset hw TSF only once, so we increment
-+	   ni_tstamp.tsf to avoid resetting the hw TSF multiple
-+	   times */
-+
-+	if (tsf == 0) {
-+		should_reset_tsf = 1;
-+		ni->ni_tstamp.tsf = cpu_to_le64(1);
-+	}
-+
- 	/* XXX conditionalize multi-bss support? */
- 	if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
- 		/*
-@@ -4449,20 +4464,61 @@
- 		if (sc->sc_stagbeacons)
- 			intval /= ATH_BCBUF;	/* for staggered beacons */
- 		if ((sc->sc_nostabeacons) &&
--		    (vap->iv_opmode == IEEE80211_M_HOSTAP))
--			nexttbtt = 0;
-+			(vap->iv_opmode == IEEE80211_M_HOSTAP))
-+			should_reset_tsf = 1;
- 	} else
- 		intval = ni->ni_intval & HAL_BEACON_PERIOD;
--	if (nexttbtt == 0)		/* e.g. for ap mode */
-+
-+#define	FUDGE	2
-+	sc->sc_syncbeacon = 0;
-+	if (should_reset_tsf) {
-+
-+		/* We just created the interface and TSF will be reset to
-+		   zero, so next beacon will be sent at the next intval
-+		   time */
-+
- 		nexttbtt = intval;
--	else if (intval)		/* NB: can be 0 for monitor mode */
--		nexttbtt = roundup(nexttbtt, intval);
--	DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
--		__func__, nexttbtt, intval, ni->ni_intval);
-+	} else if (intval) {	/* NB: can be 0 for monitor mode */
-+		if (tsf == 1) {
-+ 	
-+			/* We do not receive any beacons or probe response. Since
-+			   a beacon should be sent every 'intval' ms, we compute
-+			   the next beacon timestamp using the hardware TSF. We
-+			   ensure that it is at least FUDGE ms ahead of the
-+			   current TSF. Otherwise, we use the next beacon
-+			   timestamp again */
-+
-+			nexttbtt = roundup(hw_tsftu +1, intval);
-+			while (nexttbtt <= hw_tsftu + FUDGE) {
-+				nexttbtt += intval;
-+			}
-+		} else {
-+			if (tsf > hw_tsf) {
-+
-+			/* We do receive a beacon from someone else in the past,
-+			   but the hw TSF has not been updated (otherwise we
-+			   would have tsf >= hw_tsf). Since we cannot use the
-+			   hardware TSF, we will do nothing and wait for the
-+			   next beacon. In order to do so, we set sc->syncbeacon
-+			   again */
-+
-+				sc->sc_syncbeacon = 1;
-+				goto ath_beacon_config_debug;
-+			} else {
-+				/* We do receive a beacon in the past, normal case. We
-+				   make sure that the timestamp is at least FUDGE ms
-+				   ahead of the hardware TSF */
-+
-+				nexttbtt = tsftu + intval;
-+				while (nexttbtt <= hw_tsftu + FUDGE) {
-+					nexttbtt += intval;
-+				}
-+			}
-+		}
-+	}
-+
- 	if (ic->ic_opmode == IEEE80211_M_STA &&	!(sc->sc_nostabeacons)) {
- 		HAL_BEACON_STATE bs;
--		u_int64_t tsf;
--		u_int32_t tsftu;
- 		int dtimperiod, dtimcount;
- 		int cfpperiod, cfpcount;
- 
-@@ -4478,13 +4534,13 @@
- 			dtimcount = 0;		/* XXX? */
- 		cfpperiod = 1;			/* NB: no PCF support yet */
- 		cfpcount = 0;
--#define	FUDGE	2
- 		/*
- 		 * Pull nexttbtt forward to reflect the current
- 		 * TSF and calculate dtim+cfp state for the result.
- 		 */
--		tsf = ath_hal_gettsf64(ah);
--		tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
-+		nexttbtt = tsftu;
-+		if (nexttbtt == 0)		/* e.g. for ap mode */
-+			nexttbtt = intval;
- 		do {
- 			nexttbtt += intval;
- 			if (--dtimcount < 0) {
-@@ -4492,7 +4548,7 @@
- 				if (--cfpcount < 0)
- 					cfpcount = cfpperiod - 1;
- 			}
--		} while (nexttbtt < tsftu);
-+		} while (nexttbtt < hw_tsftu + FUDGE);
- #undef FUDGE
- 		memset(&bs, 0, sizeof(bs));
- 		bs.bs_intval = intval;
-@@ -4544,7 +4600,7 @@
- 		DPRINTF(sc, ATH_DEBUG_BEACON,
- 			"%s: tsf %llu tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n",
- 			__func__,
--			(unsigned long long) tsf, tsftu,
-+			(unsigned long long) hw_tsf, hw_tsftu,
- 			bs.bs_intval,
- 			bs.bs_nexttbtt,
- 			bs.bs_dtimperiod,
-@@ -4566,7 +4622,7 @@
- 		ath_hal_intrset(ah, sc->sc_imask);
- 	} else {
- 		ath_hal_intrset(ah, 0);
--		if (nexttbtt == intval)
-+		if (should_reset_tsf)
- 			intval |= HAL_BEACON_RESET_TSF;
- 		if (ic->ic_opmode == IEEE80211_M_IBSS) {
- 			/*
-@@ -4603,8 +4659,40 @@
- 		if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
- 			ath_beacon_start_adhoc(sc, vap);
- 	}
--	sc->sc_syncbeacon = 0;
- #undef TSF_TO_TU
-+
-+	ath_beacon_config_debug:
-+
-+	/* we print all debug messages here, in order to preserve the
-+	   time critical aspect of this function */
-+
-+	DPRINTF(sc, ATH_DEBUG_BEACON,
-+		"%s: ni=%p tsf=%llu hw_tsf=%llu tsftu=%u hw_tsftu=%u\n",
-+		__func__, ni, tsf, hw_tsf, tsftu, hw_tsftu);
-+
-+	if (should_reset_tsf) {
-+		/* we just created the interface */
-+		DPRINTF(sc, ATH_DEBUG_BEACON, "%s: first beacon\n",__func__);
-+	} else {
-+		if (tsf == 1) {
-+			/* we do not receive any beacons or probe response */
-+			DPRINTF(sc, ATH_DEBUG_BEACON,
-+				"%s: no beacon received...\n",__func__);
-+		} else {
-+			if (tsf > hw_tsf) {
-+				/* we do receive a beacon and the hw TSF has not been updated */
-+				DPRINTF(sc, ATH_DEBUG_BEACON,
-+					"%s: beacon received, but TSF is incorrect\n",__func__);
-+			} else {
-+				/* we do receive a beacon in the past, normal case */
-+				DPRINTF(sc, ATH_DEBUG_BEACON,
-+					"%s: beacon received, TSF is correct\n",__func__);
-+			}
-+		}
-+	}
-+
-+	DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt=%u intval=%u\n",
-+		__func__,nexttbtt, intval & HAL_BEACON_PERIOD);
- }
- 
- static int
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/120-soc_fix.patch kamikaze_7.09/package/madwifi/patches/120-soc_fix.patch
--- kamikaze_7.09.orig/package/madwifi/patches/120-soc_fix.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/120-soc_fix.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,46 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath_ahb.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath_ahb.c	2007-07-23 01:48:38.098151260 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath_ahb.c	2007-07-23 01:48:41.998373519 +0200
-@@ -275,11 +275,10 @@
- 
- 
- static int
--exit_ath_wmac(u_int16_t wlanNum)
-+exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
- {
- 	struct ath_ahb_softc *sc = sclist[wlanNum];
- 	struct net_device *dev;
--	const char *sysType;
- 	u_int16_t devid;
- 
- 	if (sc == NULL)
-@@ -289,13 +288,17 @@
- 	ath_detach(dev);
- 	if (dev->irq)
- 		free_irq(dev->irq, dev);
--	sysType = get_system_type();
--	if (!strcmp(sysType, "Atheros AR5315"))
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+	devid = sc->aps_sc.devid;
-+	config->tag = (unsigned long) devid;
-+#else
-+	if (!strcmp(get_system_type(), "Atheros AR5315"))
- 		devid = (u_int16_t) (sysRegRead(AR5315_SREV) &
- 			(AR5315_REV_MAJ_M | AR5315_REV_MIN_M));
- 	else
- 		devid = (u_int16_t) ((sysRegRead(AR531X_REV) >> 8) &
- 			(AR531X_REV_MAJ | AR531X_REV_MIN));
-+#endif
- 
- 	ahb_disable_wmac(devid, wlanNum);
- 	free_netdev(dev);
-@@ -401,7 +404,7 @@
- 
- static int ahb_wmac_remove(struct platform_device *pdev)
- {
--	exit_ath_wmac(pdev->id);
-+	exit_ath_wmac(pdev->id, (struct ar531x_config *) pdev->dev.platform_data);
- 
- 	return 0;
- }
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/121-ibss_hostap.patch kamikaze_7.09/package/madwifi/patches/121-ibss_hostap.patch
--- kamikaze_7.09.orig/package/madwifi/patches/121-ibss_hostap.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/121-ibss_hostap.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,250 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:41.758359843 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:42.258388337 +0200
-@@ -410,7 +410,6 @@
-  * and use the next two bits as the index of the VAP.
-  */
- #define ATH_SET_VAP_BSSID_MASK(bssid_mask)      ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))
--#define ATH_GET_VAP_ID(bssid)                   ((bssid)[0] >> 2)
- #define ATH_SET_VAP_BSSID(bssid, id) \
- 		do { \
- 			if (id) \
-@@ -1055,9 +1054,12 @@
- 			ic_opmode = opmode;
- 		break;
- 	case IEEE80211_M_IBSS:
--		if (sc->sc_nvaps != 0)		/* only one */
--			return NULL;
--		ic_opmode = opmode;
-+		if (sc->sc_nvaps == 0)		/* only one */
-+			ic_opmode = opmode;
-+		else
-+			ic_opmode = IEEE80211_M_HOSTAP;
-+
-+		sc->sc_nibssvaps++;
- 		break;
- 	case IEEE80211_M_AHDEMO:
- 	case IEEE80211_M_MONITOR:
-@@ -1087,7 +1089,7 @@
- 		return NULL;
- 	}
- 
--	if (sc->sc_nvaps >= ATH_BCBUF) {
-+	if (sc->sc_nvaps + sc->sc_nibssvaps >= ATH_BCBUF) {
- 		printk(KERN_WARNING "too many virtual APs (already got %d)\n", sc->sc_nvaps);
- 		return NULL;
- 	}
-@@ -1123,6 +1125,7 @@
- 	if (opmode == IEEE80211_M_MONITOR)
- 		dev->type = ARPHRD_IEEE80211_RADIOTAP;
- 
-+	avp->av_bslot = -1;
- 	if ((flags & IEEE80211_CLONE_BSSID) &&
- 	    opmode != IEEE80211_M_WDS && sc->sc_hasbmask) {
- 		struct ieee80211vap *v;
-@@ -1137,18 +1140,22 @@
- 
- 		/* do a full search to mark all the allocated VAPs */
- 		id_mask = 0;
--		TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)
--			id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));
-+		TAILQ_FOREACH(v, &ic->ic_vaps, iv_next) {
-+			struct ath_vap *a = (struct ath_vap *) v->iv_dev->priv;
-+			if (a->av_bslot >= 0)
-+				id_mask |= (1 << a->av_bslot);
-+		}
- 
--		for (id = 1; id < ATH_BCBUF; id++) {
-+		/* IBSS mode has local always set, so don't hand out beacon slot 0 to an IBSS vap */
-+		for (id = (opmode == IEEE80211_M_IBSS ? 1 : 0); id < ATH_BCBUF; id++) {
- 			/* get the first available slot */
- 			if ((id_mask & (1 << id)) == 0) {
- 				ATH_SET_VAP_BSSID(vap->iv_myaddr, id);
-+				avp->av_bslot = id;
- 				break;
- 			}
- 		}
- 	}
--	avp->av_bslot = -1;
- 	STAILQ_INIT(&avp->av_mcastq.axq_q);
- 	ATH_TXQ_LOCK_INIT(&avp->av_mcastq);
- 	if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_IBSS) {
-@@ -1158,33 +1165,14 @@
- 		 */
- 		avp->av_bcbuf = STAILQ_FIRST(&sc->sc_bbuf);
- 		STAILQ_REMOVE_HEAD(&sc->sc_bbuf, bf_list);
--		if (opmode == IEEE80211_M_HOSTAP || !sc->sc_hasveol) {
-+		if ((opmode == IEEE80211_M_IBSS) || (opmode == IEEE80211_M_HOSTAP) || !sc->sc_hasveol) {
- 			unsigned int slot;
--			/*
--			 * Assign the VAP to a beacon xmit slot.  As
--			 * above, this cannot fail to find one.
--			 */
--			avp->av_bslot = 0;
--			for (slot = 0; slot < ATH_BCBUF; slot++)
--				if (sc->sc_bslot[slot] == NULL) {
--					/*
--					 * XXX hack, space out slots to better
--					 * deal with misses
--					 */
--					if (slot + 1 < ATH_BCBUF &&
--					    sc->sc_bslot[slot+1] == NULL) {
--						avp->av_bslot = slot + 1;
--						break;
--					}
--					avp->av_bslot = slot;
--					/* NB: keep looking for a double slot */
--				}
- 			KASSERT(sc->sc_bslot[avp->av_bslot] == NULL,
- 				("beacon slot %u not empty?", avp->av_bslot));
- 			sc->sc_bslot[avp->av_bslot] = vap;
- 			sc->sc_nbcnvaps++;
- 		}
--		if ((opmode == IEEE80211_M_HOSTAP) && (sc->sc_hastsfadd)) {
-+		if ((sc->sc_opmode == IEEE80211_M_HOSTAP) && (sc->sc_hastsfadd)) {
- 			/*
- 			 * Multiple VAPs are to transmit beacons and we
- 			 * have h/w support for TSF adjusting; enable use
-@@ -1294,7 +1282,9 @@
- 			sc->sc_stagbeacons = 0;
- 	}
- 
--	if (vap->iv_opmode == IEEE80211_M_STA) {
-+	if (vap->iv_opmode == IEEE80211_M_IBSS) {
-+		sc->sc_nibssvaps--;
-+	} else if (vap->iv_opmode == IEEE80211_M_STA) {
- 		sc->sc_nstavaps--;
- 		sc->sc_nostabeacons = 0;
- 	} else if (vap->iv_opmode == IEEE80211_M_MONITOR)
-@@ -3383,7 +3373,7 @@
- 	    sc->sc_opmode == HAL_M_IBSS ||	/* NB: AHDEMO too */
- 	    (sc->sc_nostabeacons) || sc->sc_scanning)
- 		rfilt |= HAL_RX_FILTER_BEACON;
--	if (sc->sc_nmonvaps > 0)
-+	if ((sc->sc_nmonvaps > 0) || ((sc->sc_nvaps > 0) && (sc->sc_nibssvaps > 0)))
- 		rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
- 			  HAL_RX_FILTER_PROBEREQ | HAL_RX_FILTER_PROM);
- 	return rfilt;
-@@ -5832,12 +5822,20 @@
- 			type = ieee80211_input(ni, skb, rs->rs_rssi, rs_tsf);
- 			ieee80211_unref_node(&ni);
- 		} else {
-+			const struct ieee80211_frame_min *wh = (const struct ieee80211_frame_min *) skb->data;
- 			/*
- 			 * No key index or no entry, do a lookup and
- 			 * add the node to the mapping table if possible.
- 			 */
--			ni = ieee80211_find_rxnode(ic,
--				(const struct ieee80211_frame_min *) skb->data);
-+			if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PROBE_REQ) &&
-+					(sc->sc_nibssvaps > 0))
-+				/* if this is a probe request, send it to all vaps
-+				 * when looking up nodes, hostap will be preferred over ibss,
-+				 * because ibss will catch all nodes */
-+				ni = NULL;
-+			else
-+				ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
-+
- 			if (ni != NULL) {
- 				struct ath_node *an = ATH_NODE(ni);
- 				ieee80211_keyix_t keyix;
-Index: madwifi-ng-r2568-20070710/ath/if_athvar.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_athvar.h	2007-07-23 01:48:38.006146018 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_athvar.h	2007-07-23 01:48:42.262388566 +0200
-@@ -204,7 +204,7 @@
- #define	ATH_RXBUF	40		/* number of RX buffers */
- #define	ATH_TXBUF	200		/* number of TX buffers */
- 
--#define	ATH_BCBUF	4		/* number of beacon buffers */
-+#define	ATH_BCBUF	8		/* number of beacon buffers */
- 
- /* free buffer threshold to restart net dev */
- #define	ATH_TXBUF_FREE_THRESHOLD  (ATH_TXBUF / 20)
-@@ -603,6 +603,7 @@
- 	u_int16_t sc_nvaps;			/* # of active virtual APs */
- 	u_int8_t sc_nstavaps;			/* # of active station VAPs */
- 	u_int8_t sc_nmonvaps;			/* # of monitor VAPs */
-+	u_int8_t sc_nibssvaps;			/* # of active ibss vaps */
- 	u_int8_t sc_nbcnvaps;			/* # of vaps sending beacons */
- 	u_int sc_fftxqmin;			/* aggregation threshold */
- 	HAL_INT sc_imask;			/* interrupt mask copy */
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_beacon.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_beacon.c	2007-07-23 01:48:38.010146245 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_beacon.c	2007-07-23 01:48:42.278389477 +0200
-@@ -111,7 +111,7 @@
- 	bo->bo_tim = frm;
- 
- 	/* IBSS/TIM */
--	if (vap->iv_opmode == IEEE80211_M_IBSS) {
-+	if (ic->ic_opmode == IEEE80211_M_IBSS) {
- 		*frm++ = IEEE80211_ELEMID_IBSSPARMS;
- 		*frm++ = 2;
- 		*frm++ = 0; *frm++ = 0;		/* TODO: ATIM window */
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_input.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_input.c	2007-07-23 01:48:38.018146699 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_input.c	2007-07-23 01:48:42.282389707 +0200
-@@ -2981,7 +2981,13 @@
- 			return;
- 		}
- 		if (ni == vap->iv_bss) {
--			if (vap->iv_opmode == IEEE80211_M_IBSS) {
-+			/* this probe request may have been sent to all vaps
-+			 * to give each a chance of creating a node for this.
-+			 * important for hostap+ibss mode */
-+			ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
-+			if (ni) {
-+				allocbs = 0;
-+			} else if (vap->iv_opmode == IEEE80211_M_IBSS) {
- 				/*
- 				 * XXX Cannot tell if the sender is operating
- 				 * in ibss mode.  But we need a new node to
-@@ -2990,12 +2996,13 @@
- 				 */
- 				ni = ieee80211_fakeup_adhoc_node(vap,
- 					wh->i_addr2);
-+				allocbs = 1;
- 			} else {
- 				ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
-+				allocbs = 1;
- 			}
- 			if (ni == NULL)
- 				return;
--			allocbs = 1;
- 		}
- 
- 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_node.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_node.c	2007-07-23 01:48:41.230329754 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_node.c	2007-07-23 01:48:42.330392441 +0200
-@@ -1084,8 +1084,25 @@
- 	IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
- 
- 	hash = IEEE80211_NODE_HASH(macaddr);
-+
-+	/* look for non-ibss nodes first */
-+	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
-+		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) && ni->ni_vap->iv_opmode != IEEE80211_M_IBSS) {
-+			ieee80211_ref_node(ni);	/* mark referenced */
-+#ifdef IEEE80211_DEBUG_REFCNT
-+			IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
-+				"%s (%s:%u) %p<%s> refcnt %d\n", __func__,
-+				func, line,
-+				ni, ether_sprintf(ni->ni_macaddr),
-+				ieee80211_node_refcnt(ni));
-+#endif
-+			return ni;
-+		}
-+	}
-+
-+	/* now look for ibss nodes */
- 	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
--		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
-+		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) && ni->ni_vap->iv_opmode == IEEE80211_M_IBSS) {
- 			ieee80211_ref_node(ni);	/* mark referenced */
- #ifdef IEEE80211_DEBUG_REFCNT
- 			IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/122-replayfail_workaround.patch kamikaze_7.09/package/madwifi/patches/122-replayfail_workaround.patch
--- kamikaze_7.09.orig/package/madwifi/patches/122-replayfail_workaround.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/122-replayfail_workaround.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,14 +1,12 @@
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_linux.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_linux.c	2007-07-23 01:48:37.914140773 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_linux.c	2007-07-23 01:48:42.626409310 +0200
-@@ -285,6 +285,9 @@
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -331,6 +331,9 @@
  		k->wk_cipher->ic_name, k->wk_keyix,
- 		(unsigned long long)rsc );
+ 		(unsigned long long)rsc);
  
 +	/* disabled for now due to bogus events for unknown reasons */
 +	return;
 +
  	/* TODO: needed parameters: count, keyid, key type, src address, TSC */
- 	snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
+ 	snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,
  		k->wk_keyix,
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/123-ccmp_checks.patch kamikaze_7.09/package/madwifi/patches/123-ccmp_checks.patch
--- kamikaze_7.09.orig/package/madwifi/patches/123-ccmp_checks.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/123-ccmp_checks.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,7 +1,5 @@
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_ccmp.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_crypto_ccmp.c	2007-07-23 01:48:37.830135985 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_ccmp.c	2007-07-23 01:48:42.870423216 +0200
+--- a/net80211/ieee80211_crypto_ccmp.c
++++ b/net80211/ieee80211_crypto_ccmp.c
 @@ -475,6 +475,9 @@
  	uint8_t *mic, *pos;
  	u_int space;
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/124-linux24_compat.patch kamikaze_7.09/package/madwifi/patches/124-linux24_compat.patch
--- kamikaze_7.09.orig/package/madwifi/patches/124-linux24_compat.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/124-linux24_compat.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,9 +1,7 @@
-Index: madwifi-ng-r2568-20070710/ath/if_athvar.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_athvar.h	2007-07-23 01:48:42.262388566 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_athvar.h	2007-07-23 01:48:43.126437804 +0200
-@@ -123,6 +123,11 @@
- #define	NETDEV_TX_BUSY	1
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -126,6 +126,11 @@
+ #define ATH_GET_NETDEV_DEV(ndev)	((ndev)->class_dev.dev)
  #endif
  
 +#ifndef NETDEV_TX_OK
@@ -14,3 +12,191 @@
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
  static inline struct net_device *_alloc_netdev(int sizeof_priv, const char *mask,
  					       void (*setup)(struct net_device *))
+--- a/ath/if_ath_radar.c
++++ b/ath/if_ath_radar.c
+@@ -92,6 +92,13 @@
+ #define nofloat_pct(_value, _pct) \
+ 	( (_value * (1000 + _pct)) / 1000 )
+ 
++#ifndef list_for_each_entry_reverse
++#define list_for_each_entry_reverse(pos, head, member)			\
++	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
++	     prefetch(pos->member.prev), &pos->member != (head); 	\
++	     pos = list_entry(pos->member.prev, typeof(*pos), member))
++#endif
++
+ struct radar_pattern_specification {
+ 	/* The name of the rule/specification (i.e. what did we detect) */
+ 	const char *name;
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4705,6 +4705,46 @@
+ #undef USE_SHPREAMBLE
+ }
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
++static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
++{
++	int ret;
++	unsigned long flags;
++
++	local_irq_save(flags);
++	ret = v->counter;
++	if (likely(ret == old))
++		v->counter = new;
++	local_irq_restore(flags);
++
++	return ret;
++}
++
++/**
++ * atomic_add_unless - add unless the number is a given value
++ * @v: pointer of type atomic_t
++ * @a: the amount to add to v...
++ * @u: ...unless v is equal to u.
++ *
++ * Atomically adds @a to @v, so long as it was not @u.
++ * Returns non-zero if @v was not @u, and zero otherwise.
++ */
++static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
++{
++	int c, old;
++	c = atomic_read(v);
++	for (;;) {
++		if (unlikely(c == (u)))
++			break;
++		old = atomic_cmpxchg((v), c, c + (a));
++		if (likely(old == c))
++			break;
++		c = old;
++	}
++	return c != (u);
++}
++#endif
++
+ /*
+  * Generate beacon frame and queue cab data for a VAP.
+  */
+--- /dev/null
++++ b/net80211/sort.c
+@@ -0,0 +1,120 @@
++/*
++ * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
++ *
++ * Jan 23 2005  Matt Mackall <mpm@selenic.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++static void u32_swap(void *a, void *b, int size)
++{
++	u32 t = *(u32 *)a;
++	*(u32 *)a = *(u32 *)b;
++	*(u32 *)b = t;
++}
++
++static void generic_swap(void *a, void *b, int size)
++{
++	char t;
++
++	do {
++		t = *(char *)a;
++		*(char *)a++ = *(char *)b;
++		*(char *)b++ = t;
++	} while (--size > 0);
++}
++
++/**
++ * sort - sort an array of elements
++ * @base: pointer to data to sort
++ * @num: number of elements
++ * @size: size of each element
++ * @cmp: pointer to comparison function
++ * @swap: pointer to swap function or NULL
++ *
++ * This function does a heapsort on the given array. You may provide a
++ * swap function optimized to your element type.
++ *
++ * Sorting time is O(n log n) both on average and worst-case. While
++ * qsort is about 20% faster on average, it suffers from exploitable
++ * O(n*n) worst-case behavior and extra memory requirements that make
++ * it less suitable for kernel use.
++ */
++
++static void sort(void *base, size_t num, size_t size,
++	  int (*cmp)(const void *, const void *),
++	  void (*swap)(void *, void *, int size))
++{
++	/* pre-scale counters for performance */
++	int i = (num/2 - 1) * size, n = num * size, c, r;
++
++	if (!swap)
++		swap = (size == 4 ? u32_swap : generic_swap);
++
++	/* heapify */
++	for ( ; i >= 0; i -= size) {
++		for (r = i; r * 2 + size < n; r  = c) {
++			c = r * 2 + size;
++			if (c < n - size && cmp(base + c, base + c + size) < 0)
++				c += size;
++			if (cmp(base + r, base + c) >= 0)
++				break;
++			swap(base + r, base + c, size);
++		}
++	}
++
++	/* sort */
++	for (i = n - size; i >= 0; i -= size) {
++		swap(base, base + i, size);
++		for (r = 0; r * 2 + size < i; r = c) {
++			c = r * 2 + size;
++			if (c < i - size && cmp(base + c, base + c + size) < 0)
++				c += size;
++			if (cmp(base + r, base + c) >= 0)
++				break;
++			swap(base + r, base + c, size);
++		}
++	}
++}
++
++EXPORT_SYMBOL(sort);
++
++#if 0
++/* a simple boot-time regression test */
++
++int cmpint(const void *a, const void *b)
++{
++	return *(int *)a - *(int *)b;
++}
++
++static int sort_test(void)
++{
++	int *a, i, r = 1;
++
++	a = kmalloc(1000 * sizeof(int), GFP_KERNEL);
++	BUG_ON(!a);
++
++	printk("testing sort()\n");
++
++	for (i = 0; i < 1000; i++) {
++		r = (r * 725861) % 6599;
++		a[i] = r;
++	}
++
++	sort(a, 1000, sizeof(int), cmpint, NULL);
++
++	for (i = 0; i < 999; i++)
++		if (a[i] > a[i+1]) {
++			printk("sort() failed!\n");
++			break;
++		}
++
++	kfree(a);
++
++	return 0;
++}
++
++module_init(sort_test);
++#endif
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/125-tpc_PR_1435.patch kamikaze_7.09/package/madwifi/patches/125-tpc_PR_1435.patch
--- kamikaze_7.09.orig/package/madwifi/patches/125-tpc_PR_1435.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/125-tpc_PR_1435.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,100 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:42.258388337 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:43.370451713 +0200
-@@ -273,9 +273,7 @@
- static char *autocreate = NULL;
- static char *ratectl = DEF_RATE_CTL;
- static int rfkill = 0;
--#ifdef ATH_CAP_TPC
- static int tpc = 0;
--#endif
- static int countrycode = -1;
- static int outdoor = -1;
- static int xchanmode = -1;
-@@ -533,12 +531,6 @@
- 		rfkill ? "on" : "off");
- 	ath_hal_setrfsilent(ah, rfkill);
- 
--#ifdef ATH_CAP_TPC
--	printk(KERN_INFO "ath_pci: ath_pci: switching per-packet transmit power control %s\n",
--		tpc ? "on" : "off");
--	ath_hal_settpc(ah, tpc);
--#endif
--
- 	/*
- 	 * Setup rate tables for all potential media types.
- 	 */
-@@ -818,11 +810,18 @@
- 	 */
- #ifdef ATH_CAP_TPC
- 	sc->sc_hastpc = ath_hal_hastpc(ah);
--	if (sc->sc_hastpc || ath_hal_hastxpowlimit(ah))
-+	if(tpc && !sc->sc_hastpc) {
-+		printk(KERN_WARNING "ath_pci: WARNING: per-packet transmit power control was requested, but is not supported by the hardware.\n");
-+		tpc = 0;
-+	}
-+	printk(KERN_INFO "ath_pci: switching per-packet transmit power control %s\n",
-+		tpc ? "on" : "off");
-+	ath_hal_settpc(ah, tpc);
- #else
- 	sc->sc_hastpc = 0;
--	if (ath_hal_hastxpowlimit(ah))
-+	tpc = 0; /* TPC is always zero, when compiled without ATH_CAP_TPC */
- #endif
-+	if (sc->sc_hastpc || ath_hal_hastxpowlimit(ah))
- 		ic->ic_caps |= IEEE80211_C_TXPMGT;
- 
- 	/*
-@@ -1836,7 +1835,7 @@
- 	ath_stop_locked(dev);
- 
- #ifdef ATH_CAP_TPC
--	/* Re-enable after suspend (?) */
-+	/* Re-enable after suspend */
- 	ath_hal_settpc(ah, tpc);
- #endif
- 
-@@ -8787,26 +8786,16 @@
- 	 * Search for the VAP that needs a txpow change, if any
- 	 */
- 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
--#ifdef ATH_CAP_TPC
--		if (ic->ic_newtxpowlimit == vap->iv_bss->ni_txpower) {
-+		if (!tpc || ic->ic_newtxpowlimit >= vap->iv_bss->ni_txpower) {
- 			vap->iv_bss->ni_txpower = clamped_txpow;
- 			ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, set_node_txpower, &clamped_txpow);
- 		}
--#else
--		vap->iv_bss->ni_txpower = clamped_txpow;
--		ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, set_node_txpower, &clamped_txpow);
--#endif
- 	}
- 
--	ic->ic_newtxpowlimit = sc->sc_curtxpow = clamped_txpow;
-+	sc->sc_curtxpow = clamped_txpow;
- 
--#ifdef ATH_CAP_TPC
--	if (ic->ic_newtxpowlimit >= txpowlimit)
--		ath_hal_settxpowlimit(ah, ic->ic_newtxpowlimit);
--#else
--	if (ic->ic_newtxpowlimit != txpowlimit)
--		ath_hal_settxpowlimit(ah, ic->ic_newtxpowlimit);
--#endif
-+	if (clamped_txpow != txpowlimit)
-+		ath_hal_settxpowlimit(ah, clamped_txpow);
- }
- 
- 
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_wireless.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_wireless.c	2007-07-23 01:48:37.670126869 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_wireless.c	2007-07-23 01:48:43.374451939 +0200
-@@ -1403,6 +1403,7 @@
- 	} else {
- 		if (!fixed)		/* no change */
- 			return 0;
-+		ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX;
- 		ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED;
- 	}
- done:
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/126-rxerr_frames.patch kamikaze_7.09/package/madwifi/patches/126-rxerr_frames.patch
--- kamikaze_7.09.orig/package/madwifi/patches/126-rxerr_frames.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/126-rxerr_frames.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,10 +1,8 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:43.370451713 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:43.690469948 +0200
-@@ -5711,8 +5711,9 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6474,8 +6474,9 @@
  			/*
- 			 * Reject error frames if we have no vaps that 
+ 			 * Reject error frames if we have no vaps that
  			 * are operating in monitor mode.
 +			 * Reject empty frames as well
  			 */
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/127-beacon_node.patch kamikaze_7.09/package/madwifi/patches/127-beacon_node.patch
--- kamikaze_7.09.orig/package/madwifi/patches/127-beacon_node.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/127-beacon_node.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:43.690469948 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:43.942484311 +0200
-@@ -4027,6 +4027,8 @@
- 	}
- 	bf = avp->av_bcbuf;
- 	ni = bf->bf_node;
-+	if (!ni)
-+		return NULL;
- 
- #ifdef ATH_SUPERG_DYNTURBO
- 	/* 
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/128-adhoc_memleak.patch kamikaze_7.09/package/madwifi/patches/128-adhoc_memleak.patch
--- kamikaze_7.09.orig/package/madwifi/patches/128-adhoc_memleak.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/128-adhoc_memleak.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,26 +0,0 @@
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_input.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_input.c	2007-07-24 00:01:54.068861828 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_input.c	2007-07-24 00:02:44.035709278 +0200
-@@ -2875,7 +2875,7 @@
- 		}
- 		if ((vap->iv_opmode == IEEE80211_M_IBSS) && 
- 				(scan.capinfo & IEEE80211_CAPINFO_IBSS)) {
--			if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
-+			if (ni == vap->iv_bss) {
- 				/* Create a new entry in the neighbor table. */
- 				ni = ieee80211_add_neighbor(vap, wh, &scan);
- 			} else {
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_node.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_node.c	2007-07-24 00:02:51.284122342 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_node.c	2007-07-24 00:03:04.540877800 +0200
-@@ -1205,7 +1205,7 @@
- 	struct ieee80211com *ic = vap->iv_ic;
- 	struct ieee80211_node *ni;
- 
--	ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
-+	ni = ieee80211_dup_bss(vap, wh->i_addr2, 0);
- 	if (ni != NULL) {
- 		ni->ni_esslen = sp->ssid[1];
- 		memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/129-rxant_r2591.patch kamikaze_7.09/package/madwifi/patches/129-rxant_r2591.patch
--- kamikaze_7.09.orig/package/madwifi/patches/129-rxant_r2591.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/129-rxant_r2591.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-25 16:02:49.730126121 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-25 16:03:20.355871384 +0200
-@@ -1882,6 +1882,9 @@
- 	 */
- 	ath_update_txpow(sc);
- 
-+	/* Set the default RX antenna; it may get lost on reset. */
-+	ath_setdefantenna(sc, sc->sc_defant);
-+
- 	/*
- 	 * Setup the hardware after reset: the key cache
- 	 * is filled as needed and the receive engine is
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/131-minstrel_rateidx.patch kamikaze_7.09/package/madwifi/patches/131-minstrel_rateidx.patch
--- kamikaze_7.09.orig/package/madwifi/patches/131-minstrel_rateidx.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/131-minstrel_rateidx.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath_rate/minstrel/minstrel.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath_rate/minstrel/minstrel.c	2007-08-11 02:08:15.931956005 +0200
-+++ madwifi-ng-r2568-20070710/ath_rate/minstrel/minstrel.c	2007-08-11 02:09:37.572608440 +0200
-@@ -675,6 +675,12 @@
- 		}
- 
- 		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
-+			if (sn->rates[x].rix == 0xff) {
-+				DPRINTF(sc, "%s: %s ignore bogus rix at %d\n",
-+					dev_info, __func__, x);
-+				continue;
-+			}
-+
- 			sn->rs_rateattempts	[x] = 0;
- 			sn->rs_thisprob		[x] = 0;
- 			sn->rs_ratesuccess 	[x] = 0;
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/200-no_debug.patch kamikaze_7.09/package/madwifi/patches/200-no_debug.patch
--- kamikaze_7.09.orig/package/madwifi/patches/200-no_debug.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/200-no_debug.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,112 +1,160 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:43.942484311 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:44.466514171 +0200
-@@ -75,7 +75,7 @@
- #include <net80211/if_llc.h>
- #endif
- 
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -42,7 +42,6 @@
+  * This software is derived from work of Atsushi Onoe; his contribution
+  * is greatly appreciated.
+  */
 -#define	AR_DEBUG
-+#undef	AR_DEBUG
+ #include "if_ath_debug.h"
+ #include "opt_ah.h"
  
- #include "net80211/if_athproto.h"
- #include "if_athvar.h"
-Index: madwifi-ng-r2568-20070710/ath_rate/amrr/amrr.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath_rate/amrr/amrr.c	2007-07-23 01:48:37.298105667 +0200
-+++ madwifi-ng-r2568-20070710/ath_rate/amrr/amrr.c	2007-07-23 01:48:44.470514400 +0200
-@@ -70,7 +70,7 @@
+@@ -368,8 +367,10 @@
+ static void ath_set_dfs_cac_time(struct ieee80211com *, unsigned int seconds);
+ 
+ static unsigned int ath_test_radar(struct ieee80211com *);
+-static unsigned int ath_dump_hal_map(struct ieee80211com *ic);
++#ifdef AR_DEBUG
+ 
++static unsigned int ath_dump_hal_map(struct ieee80211com *ic);
++#endif
+ static u_int32_t ath_get_clamped_maxtxpower(struct ath_softc *sc);
+ static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, 
+ 		u_int32_t new_clamped_maxtxpower);
+@@ -520,9 +521,11 @@
+ 	u_int8_t csz;
+ 
+ 	sc->devid = devid;
++#ifdef AR_DEBUG
+ 	ath_debug_global = (ath_debug & ATH_DEBUG_GLOBAL);
+ 	sc->sc_debug 	 = (ath_debug & ~ATH_DEBUG_GLOBAL);
+ 	DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
++#endif
+ 
+ 	/* Allocate space for dynamically determined maximum VAP count */
+ 	sc->sc_bslot = 
+@@ -1038,8 +1041,9 @@
+ 	ic->ic_vap_delete = ath_vap_delete;
+ 
+ 	ic->ic_test_radar           = ath_test_radar;
++#ifdef AR_DEBUG
+ 	ic->ic_dump_hal_map	    = ath_dump_hal_map;
+-
++#endif
+ 	ic->ic_set_dfs_testmode     = ath_set_dfs_testmode;
+ 	ic->ic_get_dfs_testmode     = ath_get_dfs_testmode;
+ 
+@@ -1297,12 +1301,14 @@
+ 		/* If no default VAP debug flags are passed, allow a few to
+ 		 * transfer down from the driver to new VAPs so we can have load
+ 		 * time debugging for VAPs too. */
++#ifdef AR_DEBUG
+ 		vap->iv_debug = 0 |
+ 			((sc->sc_debug & ATH_DEBUG_RATE) ? IEEE80211_MSG_XRATE  : 0) | 
+ 			((sc->sc_debug & ATH_DEBUG_XMIT) ? IEEE80211_MSG_OUTPUT : 0) | 
+ 			((sc->sc_debug & ATH_DEBUG_RECV) ? IEEE80211_MSG_INPUT  : 0) |
+ 			0
+ 			;
++#endif
+ 	}
+ 	ic->ic_debug = (sc->sc_default_ieee80211_debug & IEEE80211_MSG_IC);
+ 
+@@ -10496,9 +10502,11 @@
+ 				/* XXX validate? */
+ 				sc->sc_ledpin = val;
+ 				break;
++#ifdef AR_DEBUG
+ 			case ATH_DEBUG:
+ 				sc->sc_debug 	 = (val & ~ATH_DEBUG_GLOBAL);
+ 				ath_debug_global = (val &  ATH_DEBUG_GLOBAL);
++#endif
+ 				break;
+ 			case ATH_TXANTENNA:
+ 				/*
+@@ -10918,9 +10926,11 @@
+ 	}
+ 
+ 	/* initialize values */
++#ifdef AR_DEBUG
+ 	ath_debug_global = (ath_debug & ATH_DEBUG_GLOBAL);
+ 	sc->sc_debug 	 = (ath_debug & ~ATH_DEBUG_GLOBAL);
+ 	sc->sc_default_ieee80211_debug = ieee80211_debug;
++#endif
+ 	sc->sc_txantenna = 0;		/* default to auto-selection */
+ 	sc->sc_txintrperiod = ATH_TXQ_INTR_PERIOD;
+ }
+@@ -11762,6 +11772,7 @@
+ }
+ 
+ /* This is called by a private ioctl (iwpriv) to dump the HAL obfuscation table */
++#ifdef AR_DEBUG
+ static unsigned int
+ ath_dump_hal_map(struct ieee80211com *ic)
+ {
+@@ -11770,7 +11781,7 @@
+ 	ath_hal_dump_map(sc->sc_ah);
+ 	return 0;
+ }
+-
++#endif
+ /* If we are shutting down or blowing off the DFS channel availability check
+  * then we call this to stop the behavior before we take the rest of the
+  * necessary actions (such as a DFS reaction to radar). */
+--- a/ath_rate/amrr/amrr.c
++++ b/ath_rate/amrr/amrr.c
+@@ -70,7 +70,9 @@
  
  #include "amrr.h"
  
--#define	AMRR_DEBUG
-+#undef	AMRR_DEBUG
++#ifdef AR_DEBUG
+ #define	AMRR_DEBUG
++#endif
  #ifdef AMRR_DEBUG
  #define	DPRINTF(sc, _fmt, ...) do {					\
  	if (sc->sc_debug & 0x10)					\
-Index: madwifi-ng-r2568-20070710/ath_rate/minstrel/minstrel.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath_rate/minstrel/minstrel.c	2007-07-23 01:48:40.974315165 +0200
-+++ madwifi-ng-r2568-20070710/ath_rate/minstrel/minstrel.c	2007-07-23 01:48:44.494515770 +0200
-@@ -117,7 +117,7 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -117,7 +117,9 @@
  
  #include "minstrel.h"
  
--#define	MINSTREL_DEBUG
-+#undef	MINSTREL_DEBUG
++#ifdef AR_DEBUG
+ #define	MINSTREL_DEBUG
++#endif
  #ifdef MINSTREL_DEBUG
  enum {
  		ATH_DEBUG_RATE		= 0x00000010	/* rate control */
-Index: madwifi-ng-r2568-20070710/ath_rate/onoe/onoe.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath_rate/onoe/onoe.c	2007-07-23 01:48:37.314106578 +0200
-+++ madwifi-ng-r2568-20070710/ath_rate/onoe/onoe.c	2007-07-23 01:48:44.518517136 +0200
-@@ -66,7 +66,7 @@
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -66,7 +66,9 @@
  
  #include "onoe.h"
  
--#define	ONOE_DEBUG
-+#undef	ONOE_DEBUG
++#ifdef AR_DEBUG
+ #define	ONOE_DEBUG
++#endif
  #ifdef ONOE_DEBUG
  enum {
  	ATH_DEBUG_RATE	= 0x00000010,	/* rate control */
-Index: madwifi-ng-r2568-20070710/ath_rate/sample/sample.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath_rate/sample/sample.c	2007-07-23 01:48:37.322107035 +0200
-+++ madwifi-ng-r2568-20070710/ath_rate/sample/sample.c	2007-07-23 01:48:44.546518731 +0200
-@@ -68,7 +68,7 @@
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -68,7 +68,9 @@
  
  #include "sample.h"
  
 -#define	SAMPLE_DEBUG
-+#undef	SAMPLE_DEBUG
++#ifdef AR_DEBUG
++#define SAMPLE_DEBUG
++#endif
  #ifdef SAMPLE_DEBUG
  enum {
- 	ATH_DEBUG_NODE		= 0x00080000,	/* node management */
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_proto.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_proto.c	2007-07-23 01:48:37.330107492 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_proto.c	2007-07-23 01:48:44.570520097 +0200
-@@ -286,6 +286,7 @@
- }
- EXPORT_SYMBOL(ieee80211_aclator_get);
- 
-+#ifdef IEEE80211_DEBUG
- void
- ieee80211_print_essid(const u_int8_t *essid, int len)
- {
-@@ -312,7 +313,6 @@
- }
- EXPORT_SYMBOL(ieee80211_print_essid);
- 
--#ifdef IEEE80211_DEBUG
- void
- ieee80211_dump_pkt(struct ieee80211com *ic,
- 	const u_int8_t *buf, int len, int rate, int rssi)
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_var.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_var.h	2007-07-23 01:48:37.338107946 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_var.h	2007-07-23 01:48:44.622523064 +0200
-@@ -35,8 +35,8 @@
- #ifndef _NET80211_IEEE80211_VAR_H_
- #define _NET80211_IEEE80211_VAR_H_
- 
--#define	IEEE80211_DEBUG
--#define	IEEE80211_DEBUG_REFCNT			/* Node reference count debugging */
-+#undef	IEEE80211_DEBUG
-+#undef	IEEE80211_DEBUG_REFCNT			/* Node reference count debugging */
- 
- /* Definitions for IEEE 802.11 drivers. */
- #include <net80211/ieee80211_linux.h>
-Index: madwifi-ng-r2568-20070710/tools/do_multi.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/do_multi.c	2007-07-23 01:48:39.754245634 +0200
-+++ madwifi-ng-r2568-20070710/tools/do_multi.c	2007-07-23 01:48:44.650524656 +0200
+ 	ATH_DEBUG_RATE		= 0x00000010,	/* rate control */
+--- a/tools/do_multi.c
++++ b/tools/do_multi.c
 @@ -9,16 +9,20 @@
  
      progname = basename(argv[0]);
  
-+#if 0
++#ifdef AR_DEBUG
      if(strcmp(progname, "80211debug") == 0)
  	ret = a80211debug_init(argc, argv);
 +#endif
@@ -116,32 +164,199 @@
  	ret = athchans_init(argc, argv);
      if(strcmp(progname, "athctrl") == 0)
  	ret =  athctrl_init(argc, argv);
-+#if 0
++#ifdef AR_DEBUG
      if(strcmp(progname, "athdebug") == 0)
  	ret =  athdebug_init(argc, argv);
 +#endif
      if(strcmp(progname, "athkey") == 0)
  	ret =  athkey_init(argc, argv);
      if(strcmp(progname, "athstats") == 0)
-Index: madwifi-ng-r2568-20070710/tools/Makefile
-===================================================================
---- madwifi-ng-r2568-20070710.orig/tools/Makefile	2007-07-23 01:48:39.798248141 +0200
-+++ madwifi-ng-r2568-20070710/tools/Makefile	2007-07-23 01:48:44.670525796 +0200
-@@ -52,7 +52,7 @@
- 	
- ifdef DOMULTI
- OBJS=	do_multi.o athstats.o 80211stats.o athkey.o athchans.o athctrl.o \
--	athdebug.o 80211debug.o wlanconfig.o
-+	wlanconfig.o
- ALL=	${OBJS} madwifi_multi
- endif
- 
-@@ -85,7 +85,7 @@
- 	${CC} -c -o do_multi.o -DDOMULTI=1 ${ALL_CFLAGS} do_multi.c
- madwifi_multi:
- 	${CC} -o madwifi_multi ${LDFLAGS} ${OBJS}
--	for i in athstats 80211stats athkey athchans athctrl athdebug wlanconfig 80211debug; do \
-+	for i in athstats 80211stats athkey athchans athctrl wlanconfig; do \
- 	ln -s -f madwifi_multi $$i; \
- 	done
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -48,6 +48,8 @@
+ 
+ all: compile
+ 
++DEBUG = -DAR_DEBUG
++
+ ALLPROGS=	athstats 80211stats athkey athchans athctrl \
+ 	athdebug 80211debug wlanconfig ath_info
+ 
+@@ -55,7 +57,7 @@
+ 
+ INCS=	-I. -I../ath -I$(HAL) -I$(TOP) -I$(ATH_HAL)
+ CFLAGS=	-g -O2 -Wall
+-ALL_CFLAGS= $(CFLAGS) $(INCS)
++ALL_CFLAGS= $(CFLAGS) $(INCS) $(DEBUG)
+ LDFLAGS=
+ 
+ 
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -29,8 +29,6 @@
+ #ifndef _NET80211_IEEE80211_LINUX_H_
+ #define _NET80211_IEEE80211_LINUX_H_
+ 
+-#define	IEEE80211_DEBUG
+-#define	IEEE80211_DEBUG_REFCNT			/* Node reference count debugging */
+ /* #define ATH_DEBUG_SPINLOCKS */		/* announce before spinlocking */
+ 
+ #include <linux/wireless.h>
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -148,7 +148,8 @@
+ TOOLS=  $(TOP)/tools 
+ 
+ WARNINGS = -Werror
+-COPTS+= $(WARNINGS)
++DEBUG = -DAR_DEBUG -DIEEE80211_DEBUG
++COPTS+= $(WARNINGS) $(DEBUG)
+ INCS=	-include $(TOP)/include/compat.h -I$(TOP)/include
+ 
+ # TARGET defines the target platform architecture. It must match one of
+--- a/ath/if_ath_radar.c
++++ b/ath/if_ath_radar.c
+@@ -19,8 +19,6 @@
+  * $Id: if_ath_radar.c 2464 2007-06-15 22:51:56Z mtaylor $
+  */
+ #include "opt_ah.h"
+-
+-#define	AR_DEBUG
+ #include "if_ath_debug.h"
+ 
+ #ifndef AUTOCONF_INCLUDED
+@@ -56,8 +54,6 @@
+ #include <net80211/if_llc.h>
+ #endif
+ 
+-#define	AR_DEBUG
+-
+ #include "net80211/if_athproto.h"
+ #include "if_athvar.h"
+ 
+--- a/ath/if_ath_hal.h
++++ b/ath/if_ath_hal.h
+@@ -1081,6 +1081,7 @@
+ 
+            tail -f /var/log/messages | sed -f hal_unmangle.sed 
+  */
++#ifdef AR_DEBUG
+ static inline void ath_hal_dump_map(struct ath_hal *ah)
+ {
+ #ifdef CONFIG_KALLSYMS
+@@ -1345,7 +1346,7 @@
+ #endif				/* #ifndef CONFIG_KALLSYMS */
+ 
+ }
+-
++#endif
+ #include "if_ath_hal_wrappers.h"
+ 
+ #endif				/* #ifndef _IF_ATH_HAL_H_ */
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -492,9 +492,10 @@
+ 	/* inject a fake radar signal -- used while on a 802.11h DFS channels */
+ 	unsigned int (*ic_test_radar)(struct ieee80211com *);
+ 
++#ifdef AR_DEBUG
+ 	/* dump HAL */
+ 	unsigned int (*ic_dump_hal_map)(struct ieee80211com *);
+-
++#endif
+ 	/* DFS channel availability check time (in seconds) */
+ 	void (*ic_set_dfs_cac_time)(struct ieee80211com *, unsigned int);
+ 	unsigned int (*ic_get_dfs_cac_time)(struct ieee80211com *);
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -1548,6 +1548,7 @@
+ 	return 0;
+ }
+ 
++#ifdef AR_DEBUG
+ static int 
+ ieee80211_ioctl_hal_map(struct net_device *dev, struct iw_request_info *info,
+        void *w, char *extra)
+@@ -1558,7 +1559,7 @@
+        params[0] = ic->ic_dump_hal_map(ic);
+        return 0;
+ }
+-
++#endif
+ 
+ static int
+ ieee80211_ioctl_radar(struct net_device *dev, struct iw_request_info *info,
+@@ -5258,8 +5259,10 @@
+ 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "getwmmparams" },
+ 	{ IEEE80211_IOCTL_RADAR,
+ 	  0, 0, "doth_radar" },
++#ifdef AR_DEBUG
+ 	{ IEEE80211_IOCTL_HALMAP,
+ 	  0, 0, "dump_hal_map" },
++#endif
+ 	/*
+ 	 * These depends on sub-ioctl support which added in version 12.
+ 	 */
+@@ -5695,7 +5698,9 @@
+ 	set_priv(IEEE80211_IOCTL_SETMLME, ieee80211_ioctl_setmlme),
+ 	set_priv(IEEE80211_IOCTL_SETKEY, ieee80211_ioctl_setkey),
+ 	set_priv(IEEE80211_IOCTL_DELKEY, ieee80211_ioctl_delkey),
++#ifdef AR_DEBUG
+ 	set_priv(IEEE80211_IOCTL_HALMAP, ieee80211_ioctl_hal_map),
++#endif
+ 	set_priv(IEEE80211_IOCTL_ADDMAC, ieee80211_ioctl_addmac),
+ 	set_priv(IEEE80211_IOCTL_DELMAC, ieee80211_ioctl_delmac),
+ 	set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
+--- a/ath/if_ath_debug.h
++++ b/ath/if_ath_debug.h
+@@ -68,13 +68,6 @@
+ 		ath_keyprint((_sc), __func__, _ix, _hk, _mac);		\
+ } while (0)
+ 
+-#else /* #ifdef AR_DEBUG */
+-
+-#define	DFLAG_ISSET(sc, _m)		0
+-#define	DPRINTF(sc, _m, _fmt, ...)
+-#define	KEYPRINTF(sc, k, ix, mac)
+-
+-#endif /* #ifdef AR_DEBUG */
+ 
+ #define	IFF_DUMPPKTS(_sc, _m)   DFLAG_ISSET((_sc), (_m))
+ 
+@@ -89,5 +82,15 @@
+ #define	IPRINTF(_sc, _fmt, ...) \
+ 		printk(KERN_INFO "%s: %s: " _fmt, \
+ 			SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
++#else
++#define	DFLAG_ISSET(sc, _m)		0
++#define	DPRINTF(sc, _m, _fmt, ...)
++#define	KEYPRINTF(sc, k, ix, mac)
++#define EPRINTF(...)
++#define WPRINTF(...)
++#define IPRINTF(...)
++#define IFF_DUMPPKTS(...) 0
++
++#endif
+ 
+ #endif /* #ifndef _IF_ATH_DEBUG_H_ */
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -920,6 +920,9 @@
+ 	ni->ni_rxkeyoff = 0;
+ }
+ 
++#ifndef IEEE80211_DEBUG
++#define node_print_message(...) do {} while(0)
++#else
+ static void node_print_message(
+ 		u_int32_t flags,
+ 		int show_counter, 
+@@ -972,7 +975,7 @@
+ 			adjusted_refcount);
+ 	va_end(args);
+ }
+-EXPORT_SYMBOL(node_print_message);
++#endif
  
+ static void
+ #ifdef IEEE80211_DEBUG_REFCNT
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/201-debug_fix.patch kamikaze_7.09/package/madwifi/patches/201-debug_fix.patch
--- kamikaze_7.09.orig/package/madwifi/patches/201-debug_fix.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/201-debug_fix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,20 @@
+--- a/ath_hal/ah_os.c
++++ b/ath_hal/ah_os.c
+@@ -65,7 +65,7 @@
+ #include <ah_os.h>
+ 
+ #ifdef AH_DEBUG
+-static	int ath_hal_debug = 0;
++static	int ath_hal_debug = 99;
+ #endif
+ 
+ int	ath_hal_dma_beacon_response_time = 2;	/* in TUs */
+@@ -327,6 +327,8 @@
+  * useful for debugging and figuring out, which hal function sets which 
+  * registers */
+ char *ath_hal_func = NULL;
++EXPORT_SYMBOL(ath_hal_func);
++
+ #endif
+ 
+ /*
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/300-napi_polling.patch kamikaze_7.09/package/madwifi/patches/300-napi_polling.patch
--- kamikaze_7.09.orig/package/madwifi/patches/300-napi_polling.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/300-napi_polling.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,58 +1,83 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:44.466514171 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:45.030546315 +0200
-@@ -170,7 +170,7 @@
- 	int, u_int64_t);
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -184,7 +184,11 @@
+ 	struct sk_buff *, int, int, u_int64_t);
  static void ath_setdefantenna(struct ath_softc *, u_int);
  static struct ath_txq *ath_txq_setup(struct ath_softc *, int, int);
 -static void ath_rx_tasklet(TQUEUE_ARG);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++static int ath_rx_poll(struct napi_struct *napi, int budget);
++#else
 +static int ath_rx_poll(struct net_device *dev, int *budget);
++#endif
  static int ath_hardstart(struct sk_buff *, struct net_device *);
  static int ath_mgtstart(struct ieee80211com *, struct sk_buff *);
  #ifdef ATH_SUPERG_COMP
-@@ -444,7 +444,6 @@
- 	ATH_TXBUF_LOCK_INIT(sc);
- 	ATH_RXBUF_LOCK_INIT(sc);
+@@ -376,6 +380,9 @@
+ 		u_int32_t new_clamped_maxtxpower);
+ static u_int32_t ath_get_real_maxtxpower(struct ath_softc *sc);
+ 
++static void ath_poll_disable(struct net_device *dev);
++static void ath_poll_enable(struct net_device *dev);
++
+ /* calibrate every 30 secs in steady state but check every second at first. */
+ static int ath_calinterval = ATH_SHORT_CALINTERVAL;
+ static int ath_countrycode = CTRY_DEFAULT;	/* country code */
+@@ -547,7 +554,6 @@
+ 
+ 	atomic_set(&sc->sc_txbuf_counter, 0);
  
 -	ATH_INIT_TQUEUE(&sc->sc_rxtq,     ath_rx_tasklet,	dev);
  	ATH_INIT_TQUEUE(&sc->sc_txtq,	  ath_tx_tasklet,	dev);
  	ATH_INIT_TQUEUE(&sc->sc_bmisstq,  ath_bmiss_tasklet,	dev);
  	ATH_INIT_TQUEUE(&sc->sc_bstucktq, ath_bstuck_tasklet,	dev);
-@@ -691,6 +690,8 @@
+@@ -821,6 +827,12 @@
  	dev->set_mac_address = ath_set_mac_address;
-  	dev->change_mtu = ath_change_mtu;
- 	dev->tx_queue_len = ATH_TXBUF - 1;		/* 1 for mgmt frame */
+ 	dev->change_mtu = ath_change_mtu;
+ 	dev->tx_queue_len = ATH_TXBUF - ATH_TXBUF_MGT_RESERVED;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++	netif_napi_add(dev, &sc->sc_napi, ath_rx_poll, 64);
++#else
 +	dev->poll = ath_rx_poll;
 +	dev->weight = 64;
++#endif
  #ifdef USE_HEADERLEN_RESV
  	dev->hard_header_len += sizeof(struct ieee80211_qosframe) +
  				sizeof(struct llc) +
-@@ -1667,6 +1668,7 @@
- 	 */
- 	ath_hal_getisr(ah, &status);		/* NB: clears ISR too */
- 	DPRINTF(sc, ATH_DEBUG_INTR, "%s: status 0x%x\n", __func__, status);
+@@ -2216,6 +2228,7 @@
+ 		(status & HAL_INT_GLOBAL)	? " HAL_INT_GLOBAL"	: ""
+ 		);
+ 
 +	sc->sc_isr = status;
  	status &= sc->sc_imask;			/* discard unasked for bits */
- 	if (status & HAL_INT_FATAL) {
- 		sc->sc_stats.ast_hardware++;
-@@ -1702,7 +1704,14 @@
- 		if (status & HAL_INT_RX) {
- 			sc->sc_tsf = ath_hal_gettsf64(ah);
- 			ath_uapsd_processtriggers(sc);
+ 	/* As soon as we know we have a real interrupt we intend to service, 
+ 	 * we will check to see if we need an initial hardware TSF reading. 
+@@ -2273,7 +2286,23 @@
+ 		}
+ 		if (status & (HAL_INT_RX | HAL_INT_RXPHY)) {
+ 			ath_uapsd_processtriggers(sc, hw_tsf);
 -			ATH_SCHEDULE_TQUEUE(&sc->sc_rxtq, &needmark);
 +			sc->sc_isr &= ~HAL_INT_RX;
-+			if (netif_rx_schedule_prep(dev)) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++			if (netif_rx_schedule_prep(dev, &sc->sc_napi))
++#else
++			if (netif_rx_schedule_prep(dev))
++#endif
++			{
 +#ifndef ATH_PRECISE_TSF
 +				sc->sc_imask &= ~HAL_INT_RX;
 +				ath_hal_intrset(ah, sc->sc_imask);
 +#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++				__netif_rx_schedule(dev, &sc->sc_napi);
++#else
 +				__netif_rx_schedule(dev);
++#endif
 +			}
  		}
  		if (status & HAL_INT_TX) {
  #ifdef ATH_SUPERG_DYNTURBO
-@@ -1728,6 +1737,11 @@
+@@ -2299,6 +2328,11 @@
  				}
  			}
  #endif
@@ -64,75 +89,149 @@
  			ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
  		}
  		if (status & HAL_INT_BMISS) {
-@@ -3315,10 +3329,10 @@
- 	 *
- 	 * XXX Using in_softirq is not right since we might
- 	 * be called from other soft irq contexts than
--	 * ath_rx_tasklet.
+@@ -2511,6 +2545,7 @@
+ 	if (sc->sc_tx99 != NULL)
+ 		sc->sc_tx99->start(sc->sc_tx99);
+ #endif
++	ath_poll_enable(dev);
+ 
+ done:
+ 	ATH_UNLOCK(sc);
+@@ -2551,6 +2586,9 @@
+ 		if (sc->sc_tx99 != NULL)
+ 			sc->sc_tx99->stop(sc->sc_tx99);
+ #endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++		ath_poll_disable(dev);
++#endif
+ 		netif_stop_queue(dev);	/* XXX re-enabled by ath_newstate */
+ 		dev->flags &= ~IFF_RUNNING;	/* NB: avoid recursion */
+ 		ieee80211_stop_running(ic);	/* stop all VAPs */
+@@ -4009,6 +4047,39 @@
+ 	return ath_keyset(sc, k, mac, vap->iv_bss);
+ }
+ 
++static void ath_poll_disable(struct net_device *dev)
++{
++	struct ath_softc *sc = dev->priv;
++
++	/*
++	 * XXX Using in_softirq is not right since we might
++	 * be called from other soft irq contexts than
 +	 * ath_rx_poll
++	 */
++	if (!in_softirq()) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++		napi_disable(&sc->sc_napi);
++#else
++		netif_poll_disable(dev);
++#endif
++	}
++}
++
++static void ath_poll_enable(struct net_device *dev)
++{
++	struct ath_softc *sc = dev->priv;
++
++	/* NB: see above */
++	if (!in_softirq()) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++		napi_enable(&sc->sc_napi);
++#else
++		netif_poll_enable(dev);
++#endif
++	}
++}
++
++
+ /*
+  * Block/unblock tx+rx processing while a key change is done.
+  * We assume the caller serializes key management operations
+@@ -4026,13 +4097,7 @@
+ 	 * When called from the rx tasklet we cannot use
+ 	 * tasklet_disable because it will block waiting
+ 	 * for us to complete execution.
+-	 *
+-	 * XXX Using in_softirq is not right since we might
+-	 * be called from other soft irq contexts than
+-	 * ath_rx_tasklet.
  	 */
- 	if (!in_softirq())
+-	if (!in_softirq())
 -		tasklet_disable(&sc->sc_rxtq);
-+		netif_poll_disable(dev);
  	netif_stop_queue(dev);
  }
  
-@@ -3331,7 +3345,7 @@
- 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
- 	netif_start_queue(dev);
- 	if (!in_softirq())		/* NB: see above */
+@@ -4043,9 +4108,9 @@
+ 	struct ath_softc *sc = dev->priv;
+ 
+ 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
+-	netif_wake_queue(dev);
+-	if (!in_softirq())		/* NB: see above */
 -		tasklet_enable(&sc->sc_rxtq);
-+		netif_poll_enable(dev);
++
++	if (dev->flags&IFF_RUNNING)
++		netif_wake_queue(dev);
  }
  
  /*
-@@ -5586,13 +5600,12 @@
+@@ -6350,15 +6415,25 @@
  	sc->sc_rxotherant = 0;
  }
  
 -static void
 -ath_rx_tasklet(TQUEUE_ARG data)
 +static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++ath_rx_poll(struct napi_struct *napi, int budget)
++#else
 +ath_rx_poll(struct net_device *dev, int *budget)
++#endif
  {
  #define	PA2DESC(_sc, _pa) \
  	((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
  		((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
 -	struct net_device *dev = (struct net_device *)data;
- 	struct ath_buf *bf;
+-	struct ath_buf *bf;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++	struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi);
++	struct net_device *dev = sc->sc_dev;
++	u_int rx_limit = budget;
++#else
  	struct ath_softc *sc = dev->priv;
++	u_int rx_limit = min(dev->quota, *budget);
++#endif
++	struct ath_buf *bf;
  	struct ieee80211com *ic = &sc->sc_ic;
-@@ -5605,12 +5618,15 @@
+ 	struct ath_hal *ah = sc ? sc->sc_ah : NULL;
+ 	struct ath_desc *ds;
+@@ -6368,8 +6443,10 @@
+ 	unsigned int len;
  	int type;
  	u_int phyerr;
- 	u_int64_t rs_tsf;
 +	u_int processed = 0, early_stop = 0;
-+	u_int rx_limit = dev->quota;
  
- 	/* Let the 802.11 layer know about the new noise floor */
- 	sc->sc_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
- 	ic->ic_channoise = sc->sc_channoise;
- 
- 	DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s\n", __func__);
+ 	DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n");
 +process_rx_again:
  	do {
  		bf = STAILQ_FIRST(&sc->sc_rxbuf);
  		if (bf == NULL) {		/* XXX ??? can this happen */
-@@ -5634,6 +5650,13 @@
+@@ -6393,6 +6470,15 @@
  			/* NB: never process the self-linked entry at the end */
  			break;
  		}
 +
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
 +		processed++;
++#endif
 +		if (rx_limit-- < 0) {
 +			early_stop = 1;
 +			break;
 +		}
 +
  		skb = bf->bf_skb;
- 		if (skb == NULL) {		/* XXX ??? can this happen */
- 			printk("%s: no skbuff (%s)\n", DEV_NAME(dev), __func__);
-@@ -5672,6 +5695,7 @@
+ 		if (skb == NULL) {
+ 			EPRINTF(sc, "Dropping; buffer contains NULL skbuff.\n");
+@@ -6440,6 +6526,7 @@
  				sc->sc_stats.ast_rx_phyerr++;
  				phyerr = rs->rs_phyerr & 0x1f;
  				sc->sc_stats.ast_rx_phy[phyerr]++;
@@ -140,43 +239,55 @@
  			}
  			if (rs->rs_status & HAL_RXERR_DECRYPT) {
  				/*
-@@ -5889,9 +5913,33 @@
+@@ -6635,9 +6722,43 @@
  		STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
  		ATH_RXBUF_UNLOCK_IRQ(sc);
  	} while (ath_rxbuf_init(sc, bf) == 0);
 +	if (!early_stop) {
++		unsigned long flags;
 +		/* Check if more data is received while we were
 +		 * processing the descriptor chain.
 +		 */
 +#ifndef ATH_PRECISE_TSF
-+		ATH_DISABLE_INTR();
++		local_irq_save(flags);
 +		if (sc->sc_isr & HAL_INT_RX) {
++			u_int64_t hw_tsf = ath_hal_gettsf64(ah);
 +			sc->sc_isr &= ~HAL_INT_RX;
-+			ATH_ENABLE_INTR();
-+			ath_uapsd_processtriggers(sc);
++			local_irq_restore(flags);
++			ath_uapsd_processtriggers(sc, hw_tsf);
 +			goto process_rx_again;
 +		}
 +#endif
-+		netif_rx_complete(dev);
-+
 +#ifndef ATH_PRECISE_TSF
 +		sc->sc_imask |= HAL_INT_RX;
 +		ath_hal_intrset(ah, sc->sc_imask);
-+		ATH_ENABLE_INTR();
++		local_irq_restore(flags);
 +#endif
 +	}
 +
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++	netif_rx_complete(dev, napi);
++#else
++	netif_rx_complete(dev);
 +	*budget -= processed;
++	dev->quota -= processed;
++#endif
  
  	/* rx signal state monitoring */
  	ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++	return processed;
++#else
 +	return early_stop;
++#endif
  #undef PA2DESC
  }
  
-@@ -7514,11 +7562,22 @@
+@@ -8288,12 +8409,24 @@
+ {
  	struct net_device *dev = (struct net_device *)data;
  	struct ath_softc *sc = dev->priv;
++	unsigned long flags;
  
 +process_tx_again:
  	if (txqactive(sc->sc_ah, 0))
@@ -184,96 +295,89 @@
  	if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
  		ath_tx_processq(sc, sc->sc_cabq);
  
-+	ATH_DISABLE_INTR();
++	local_irq_save(flags);
 +	if (sc->sc_isr & HAL_INT_TX) {
 +		sc->sc_isr &= ~HAL_INT_TX;
-+		ATH_ENABLE_INTR();
++		local_irq_restore(flags);
 +		goto process_tx_again;
 +	}
 +	sc->sc_imask |= HAL_INT_TX;
 +	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
-+	ATH_ENABLE_INTR();
++	local_irq_restore(flags);
 +
  	netif_wake_queue(dev);
  
  	if (sc->sc_softled)
-@@ -7535,6 +7594,7 @@
+@@ -8309,7 +8442,9 @@
+ {
  	struct net_device *dev = (struct net_device *)data;
  	struct ath_softc *sc = dev->priv;
++	unsigned long flags;
  
 +process_tx_again:
  	/*
  	 * Process each active queue.
  	 */
-@@ -7555,6 +7615,16 @@
+@@ -8330,6 +8465,16 @@
  	if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum))
  		ath_tx_processq(sc, sc->sc_uapsdq);
  
-+	ATH_DISABLE_INTR();
++	local_irq_save(flags);
 +	if (sc->sc_isr & HAL_INT_TX) {
 +		sc->sc_isr &= ~HAL_INT_TX;
-+		ATH_ENABLE_INTR();
++		local_irq_restore(flags);
 +		goto process_tx_again;
 +	}
 +	sc->sc_imask |= HAL_INT_TX;
 +	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
-+	ATH_ENABLE_INTR();
++	local_irq_restore(flags);
 +
  	netif_wake_queue(dev);
  
  	if (sc->sc_softled)
-@@ -7572,6 +7642,7 @@
+@@ -8345,13 +8490,25 @@
+ 	struct net_device *dev = (struct net_device *)data;
+ 	struct ath_softc *sc = dev->priv;
  	unsigned int i;
++	unsigned long flags;
  
- 	/* Process each active queue. */
+ 	/* Process each active queue. This includes sc_cabq, sc_xrtq and
+ 	 * sc_uapsdq */
 +process_tx_again:
  	for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
  		if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i))
  			ath_tx_processq(sc, &sc->sc_txq[i]);
-@@ -7580,6 +7651,16 @@
- 		ath_tx_processq(sc, sc->sc_xrtxq);
- #endif
  
-+	ATH_DISABLE_INTR();
++	local_irq_save(flags);
 +	if (sc->sc_isr & HAL_INT_TX) {
 +		sc->sc_isr &= ~HAL_INT_TX;
-+		ATH_ENABLE_INTR();
++		local_irq_restore(flags);
 +		goto process_tx_again;
 +	}
 +	sc->sc_imask |= HAL_INT_TX;
 +	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
-+	ATH_ENABLE_INTR();
++	local_irq_restore(flags);
 +
  	netif_wake_queue(dev);
  
  	if (sc->sc_softled)
-@@ -7678,6 +7759,7 @@
- ath_draintxq(struct ath_softc *sc)
- {
- 	struct ath_hal *ah = sc->sc_ah;
-+	int npend = 0;
- 	unsigned int i;
- 
- 	/* XXX return value */
-@@ -9186,9 +9268,9 @@
+@@ -10284,9 +10441,9 @@
  	dev->mtu = mtu;
  	if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) {
  		/* NB: the rx buffers may need to be reallocated */
 -		tasklet_disable(&sc->sc_rxtq);
-+		netif_poll_disable(dev);
++		ath_poll_disable(dev);
  		error = ath_reset(dev);
 -		tasklet_enable(&sc->sc_rxtq);
-+		netif_poll_enable(dev);
++		ath_poll_enable(dev);
  	}
  	ATH_UNLOCK(sc);
  
-Index: madwifi-ng-r2568-20070710/ath/if_athvar.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_athvar.h	2007-07-23 01:48:43.126437804 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_athvar.h	2007-07-23 01:48:45.030546315 +0200
-@@ -49,6 +49,10 @@
- #include "net80211/ieee80211.h"		/* XXX for WME_NUM_AC */
- #include <asm/io.h>
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -53,6 +53,10 @@
+ # include	<asm/bitops.h>
+ #endif
  
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 +#define irqs_disabled()			0
@@ -282,7 +386,17 @@
  /*
   * Deduce if tasklets are available.  If not then
   * fall back to using the immediate work queue.
-@@ -635,7 +639,6 @@
+@@ -616,6 +620,9 @@
+ struct ath_softc {
+ 	struct ieee80211com sc_ic;		/* NB: must be first */
+ 	struct net_device *sc_dev;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++	struct napi_struct sc_napi;
++#endif
+ 	void __iomem *sc_iobase;		/* address of the device */
+ 	struct semaphore sc_lock;		/* dev-level lock */
+ 	struct net_device_stats	sc_devstats;	/* device statistics */
+@@ -730,7 +737,6 @@
  	struct ath_buf *sc_rxbufcur;		/* current rx buffer */
  	u_int32_t *sc_rxlink;			/* link ptr in last RX desc */
  	spinlock_t sc_rxbuflock;
@@ -290,7 +404,7 @@
  	struct ATH_TQ_STRUCT sc_rxorntq;	/* rxorn intr tasklet */
  	u_int8_t sc_defant;			/* current default antenna */
  	u_int8_t sc_rxotherant;			/* RXs on non-default antenna */
-@@ -648,6 +651,7 @@
+@@ -745,6 +751,7 @@
  	u_int sc_txintrperiod;			/* tx interrupt batching */
  	struct ath_txq sc_txq[HAL_NUM_TX_QUEUES];
  	struct ath_txq *sc_ac2q[WME_NUM_AC];	/* WME AC -> h/w qnum */
@@ -298,28 +412,120 @@
  	struct ATH_TQ_STRUCT sc_txtq;		/* tx intr tasklet */
  	u_int8_t sc_grppoll_str[GRPPOLL_RATE_STR_LEN];
  	struct ath_descdma sc_bdma;		/* beacon descriptors */
-@@ -720,6 +724,8 @@
- #define	ATH_TXBUF_LOCK_ASSERT(_sc) \
- 	KASSERT(spin_is_locked(&(_sc)->sc_txbuflock), ("txbuf not locked!"))
+@@ -858,6 +865,8 @@
+ #define	ATH_TXBUF_LOCK_CHECK(_sc)
+ #endif
  
 +#define ATH_DISABLE_INTR		local_irq_disable
 +#define ATH_ENABLE_INTR 		local_irq_enable
  
  #define	ATH_RXBUF_LOCK_INIT(_sc)	spin_lock_init(&(_sc)->sc_rxbuflock)
  #define	ATH_RXBUF_LOCK_DESTROY(_sc)
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_input.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_input.c	2007-07-23 01:48:44.214499810 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_input.c	2007-07-23 01:48:45.030546315 +0200
-@@ -1128,8 +1128,9 @@
- 		if (ni->ni_vlan != 0 && vap->iv_vlgrp != NULL) {
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1198,7 +1198,7 @@
  			/* attach vlan tag */
- 			vlan_hwaccel_receive_skb(skb, vap->iv_vlgrp, ni->ni_vlan);
--		} else
--			netif_rx(skb);
-+		} else {
-+			netif_receive_skb(skb);
-+		}
- 		dev->last_rx = jiffies;
- 	}
+ 			struct ieee80211_node *ni_tmp = SKB_CB(skb)->ni;
+ 			if (vlan_hwaccel_receive_skb(skb, vap->iv_vlgrp, ni->ni_vlan) == NET_RX_DROP) {
+-				/* If netif_rx dropped the packet because 
++				/* If netif_receive_skb dropped the packet because
+ 				 * device was too busy */
+ 				if (ni_tmp != NULL) {
+ 					/* node reference was leaked */
+@@ -1209,8 +1209,8 @@
+ 			skb = NULL; /* SKB is no longer ours */
+ 		} else {
+ 			struct ieee80211_node *ni_tmp = SKB_CB(skb)->ni;
+-			if (netif_rx(skb) == NET_RX_DROP) {
+-				/* If netif_rx dropped the packet because 
++			if (netif_receive_skb(skb) == NET_RX_DROP) {
++				/* If netif_receive_skb dropped the packet because
+ 				 * device was too busy */
+ 				if (ni_tmp != NULL) {
+ 					/* node reference was leaked */
+@@ -2322,8 +2322,8 @@
+ 		skb1->protocol = __constant_htons(0x0019);  /* ETH_P_80211_RAW */
+ 
+ 		ni_tmp = SKB_CB(skb1)->ni;
+-		if (netif_rx(skb1) == NET_RX_DROP) {
+-			/* If netif_rx dropped the packet because 
++		if (netif_receive_skb(skb1) == NET_RX_DROP) {
++			/* If netif_receive_skb dropped the packet because
+ 			 * device was too busy */
+ 			if (ni_tmp != NULL) {
+ 				/* node reference was leaked */
+--- a/net80211/ieee80211_monitor.c
++++ b/net80211/ieee80211_monitor.c
+@@ -584,8 +584,8 @@
+ 			skb1->protocol = 
+ 				__constant_htons(0x0019); /* ETH_P_80211_RAW */
+ 
+-			if (netif_rx(skb1) == NET_RX_DROP) {
+-				/* If netif_rx dropped the packet because 
++			if (netif_receive_skb(skb1) == NET_RX_DROP) {
++				/* If netif_receive_skb dropped the packet because
+ 				 * device was too busy, reclaim the ref. in 
+ 				 * the skb. */
+ 				if (SKB_CB(skb1)->ni != NULL)
+--- a/net80211/ieee80211_skb.c
++++ b/net80211/ieee80211_skb.c
+@@ -73,7 +73,7 @@
+ #undef dev_queue_xmit
+ #undef kfree_skb
+ #undef kfree_skb_fast
+-#undef netif_rx
++#undef netif_receive_skb
+ #undef pskb_copy
+ #undef skb_clone
+ #undef skb_copy
+@@ -638,8 +638,8 @@
+ 		grp, vlan_tag);
+ }
+ 
+-int netif_rx_debug(struct sk_buff *skb, const char* func, int line) {
+-	return netif_rx(untrack_skb(skb, 0, func, line, __func__, __LINE__));
++int netif_receive_skb_debug(struct sk_buff *skb, const char* func, int line) {
++	return netif_receive_skb(untrack_skb(skb, 0, func, line, __func__, __LINE__));
  }
+ 
+ struct sk_buff * alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
+@@ -760,7 +760,7 @@
+ }
+ 
+ EXPORT_SYMBOL(vlan_hwaccel_receive_skb_debug);
+-EXPORT_SYMBOL(netif_rx_debug);
++EXPORT_SYMBOL(netif_receive_skb_debug);
+ EXPORT_SYMBOL(alloc_skb_debug);
+ EXPORT_SYMBOL(dev_alloc_skb_debug);
+ EXPORT_SYMBOL(skb_clone_debug);
+--- a/net80211/ieee80211_skb.h
++++ b/net80211/ieee80211_skb.h
+@@ -116,7 +116,7 @@
+ int  vlan_hwaccel_receive_skb_debug(struct sk_buff *skb, 
+ 				    struct vlan_group *grp, unsigned short vlan_tag, 
+ 				    const char* func, int line);
+-int netif_rx_debug(struct sk_buff *skb, const char* func, int line);
++int netif_receive_skb_debug(struct sk_buff *skb, const char* func, int line);
+ struct sk_buff * alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
+ 				 const char *func, int line);
+ struct sk_buff * dev_alloc_skb_debug(unsigned int length,
+@@ -151,7 +151,7 @@
+ #undef dev_queue_xmit
+ #undef kfree_skb
+ #undef kfree_skb_fast
+-#undef netif_rx
++#undef netif_receive_skb
+ #undef pskb_copy
+ #undef skb_clone
+ #undef skb_copy
+@@ -168,8 +168,8 @@
+ 	skb_copy_expand_debug(_skb, _newheadroom, _newtailroom, _gfp_mask, __func__, __LINE__)
+ #define vlan_hwaccel_receive_skb(_skb, _grp, _tag) \
+ 	vlan_hwaccel_receive_skb_debug(_skb, _grp, _tag, __func__, __LINE__)
+-#define netif_rx(_skb) \
+-	netif_rx_debug(_skb, __func__, __LINE__)
++#define netif_receive_skb(_skb) \
++	netif_receive_skb_debug(_skb, __func__, __LINE__)
+ #define	alloc_skb(_length, _gfp_mask) \
+ 	alloc_skb_debug(_length, _gfp_mask, __func__, __LINE__)
+ #define	dev_alloc_skb(_length) \
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/301-tx_locking.patch kamikaze_7.09/package/madwifi/patches/301-tx_locking.patch
--- kamikaze_7.09.orig/package/madwifi/patches/301-tx_locking.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/301-tx_locking.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,77 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:45.030546315 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:45.406567742 +0200
-@@ -2558,7 +2558,7 @@
- 	/* NB: use this lock to protect an->an_tx_ffbuf (and txq->axq_stageq)
- 	 *	in athff_can_aggregate() call too.
- 	 */
--	ATH_TXQ_LOCK_IRQ(txq);
-+	ATH_TXQ_LOCK_BH(txq);
- 	if (athff_can_aggregate(sc, eh, an, skb, vap->iv_fragthreshold, &ff_flush)) {
- 		if (an->an_tx_ffbuf[skb->priority]) { /* i.e., frame on the staging queue */
- 			bf = an->an_tx_ffbuf[skb->priority];
-@@ -2566,6 +2566,7 @@
- 			/* get (and remove) the frame from staging queue */
- 			TAILQ_REMOVE(&txq->axq_stageq, bf, bf_stagelist);
- 			an->an_tx_ffbuf[skb->priority] = NULL;
-+			ATH_TXQ_UNLOCK_BH(txq);
- 
- 			/*
- 			 * chain skbs and add FF magic
-@@ -2588,7 +2589,7 @@
- 			 */
- 			ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
- 			if (bf == NULL) {
--				ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
-+				ATH_TXQ_UNLOCK_BH(txq);
- 				goto hardstart_fail;
- 			}
- 			DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
-@@ -2600,8 +2601,7 @@
- 			an->an_tx_ffbuf[skb->priority] = bf;
- 
- 			TAILQ_INSERT_HEAD(&txq->axq_stageq, bf, bf_stagelist);
--
--			ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
-+			ATH_TXQ_UNLOCK_BH(txq);
- 
- 			return NETDEV_TX_OK;
- 		}
-@@ -2614,7 +2614,7 @@
- 			an->an_tx_ffbuf[skb->priority] = NULL;
- 
- 			/* NB: ath_tx_start -> ath_tx_txqaddbuf uses ATH_TXQ_LOCK too */
--			ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
-+			ATH_TXQ_UNLOCK_BH(txq);
- 
- 			/* encap and xmit */
- 			bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
-@@ -2663,12 +2663,12 @@
- 
- 		ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
- 		if (bf == NULL) {
--			ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
-+			ATH_TXQ_UNLOCK_BH(txq);
- 			goto hardstart_fail;
- 		}
-+		ATH_TXQ_UNLOCK_BH(txq);
- 	}
- 
--	ATH_TXQ_UNLOCK_IRQ(txq);
- 
- ff_flush_done:
- ff_bypass:
-Index: madwifi-ng-r2568-20070710/ath/if_athvar.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_athvar.h	2007-07-23 01:48:45.030546315 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_athvar.h	2007-07-23 01:48:45.406567742 +0200
-@@ -497,6 +497,8 @@
- #define ATH_TXQ_INTR_PERIOD		5  /* axq_intrcnt period for intr gen */
- #define	ATH_TXQ_LOCK_INIT(_tq)		spin_lock_init(&(_tq)->axq_lock)
- #define	ATH_TXQ_LOCK_DESTROY(_tq)
-+#define ATH_TXQ_LOCK_BH(_tq)		spin_lock_bh(&(_tq)->axq_lock);
-+#define ATH_TXQ_UNLOCK_BH(_tq)		spin_unlock_bh(&(_tq)->axq_lock);
- #define ATH_TXQ_LOCK_IRQ(_tq)		do {				\
- 	unsigned long __axq_lockflags;					\
- 	spin_lock_irqsave(&(_tq)->axq_lock, __axq_lockflags);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/305-pureg_fix.patch kamikaze_7.09/package/madwifi/patches/305-pureg_fix.patch
--- kamikaze_7.09.orig/package/madwifi/patches/305-pureg_fix.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/305-pureg_fix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,8 +1,6 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:45.406567742 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:45.690583928 +0200
-@@ -3384,7 +3384,9 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4149,7 +4149,9 @@
  		rfilt |= HAL_RX_FILTER_PROM;
  	if (ic->ic_opmode == IEEE80211_M_STA ||
  	    sc->sc_opmode == HAL_M_IBSS ||	/* NB: AHDEMO too */
@@ -11,47 +9,56 @@
 +		((ic->ic_opmode == IEEE80211_M_HOSTAP) &&
 +		 (ic->ic_protmode != IEEE80211_PROT_NONE)))
  		rfilt |= HAL_RX_FILTER_BEACON;
- 	if ((sc->sc_nmonvaps > 0) || ((sc->sc_nvaps > 0) && (sc->sc_nibssvaps > 0)))
+ 	if (sc->sc_nmonvaps > 0)
  		rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_input.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_input.c	2007-07-23 01:48:45.030546315 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_input.c	2007-07-23 01:48:45.690583928 +0200
-@@ -321,11 +321,12 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -346,11 +346,12 @@
  				bssid = wh->i_addr3;
  			}
  			/*
 -			 * Validate the bssid.
 +			 * Validate the bssid. Let beacons get through though for 11g protection mode.
  			 */
- #ifdef ATH_SUPERG_XR
- 			if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) &&
+-#ifdef ATH_SUPERG_XR
+ 			if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
 -			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
 +			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
 +				(subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
++#ifdef ATH_SUPERG_XR
  				/*
  				 * allow MGT frames to vap->iv_xrvap.
  				 * this will allow roaming between  XR and normal vaps
-@@ -344,7 +345,8 @@
- 			}
+@@ -366,18 +367,14 @@
+ 					vap->iv_stats.is_rx_wrongbss++;
+ 					goto out;
+ 				}
+-			}
  #else
- 			if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) &&
+-			if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
 -			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
-+			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
-+				(subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
  				/* not interested in */
  				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  					bssid, NULL, "%s", "not to bss");
-@@ -2541,7 +2543,7 @@
+ 				vap->iv_stats.is_rx_wrongbss++;
+ 				goto out;
+-			}
+-
+ #endif
++			}
+ 			break;
+ 		case IEEE80211_M_WDS:
+ 			if (skb->len < sizeof(struct ieee80211_frame_addr4)) {
+@@ -3066,7 +3063,7 @@
  	u_int8_t *frm, *efrm;
- 	u_int8_t *ssid, *rates, *xrates, *wpa, *rsn, *wme, *ath;
+ 	u_int8_t *ssid, *rates, *xrates, *suppchan, *wpa, *rsn, *wme, *ath;
  	u_int8_t rate;
 -	int reassoc, resp, allocbs = 0;
 +	int reassoc, resp, allocbs = 0, has_erp = 0;
  	u_int8_t qosinfo;
  
- 	wh = (struct ieee80211_frame *) skb->data;
-@@ -2563,11 +2565,15 @@
+ 	if (ni_or_null == NULL)
+@@ -3096,11 +3093,15 @@
  		 *    o station mode when associated (to collect state
  		 *      updates such as 802.11g slot time), or
  		 *    o adhoc mode (to discover neighbors)
@@ -68,7 +75,7 @@
  			vap->iv_stats.is_rx_mgtdiscard++;
  			return;
  		}
-@@ -2650,6 +2656,7 @@
+@@ -3184,6 +3185,7 @@
  					break;
  				}
  				scan.erp = frm[2];
@@ -76,7 +83,7 @@
  				break;
  			case IEEE80211_ELEMID_RSN:
  				scan.rsn = frm;
-@@ -2867,6 +2874,20 @@
+@@ -3421,6 +3423,20 @@
  				ieee80211_bg_scan(vap);
  			return;
  		}
@@ -97,11 +104,9 @@
  		/*
  		 * If scanning, just pass information to the scan module.
  		 */
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_node.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_node.c	2007-07-23 01:48:42.330392441 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_node.c	2007-07-23 01:48:45.694584154 +0200
-@@ -332,10 +332,16 @@
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -383,10 +383,16 @@
  	/* Update country ie information */
  	ieee80211_build_countryie(ic);
  
@@ -120,11 +125,9 @@
  
  	(void) ieee80211_sta_join1(PASS_NODE(ni));
  }
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_proto.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_proto.c	2007-07-23 01:48:44.570520097 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_proto.c	2007-07-23 01:48:45.718585522 +0200
-@@ -586,6 +586,28 @@
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -595,6 +595,28 @@
  	{ 4, { 2, 4, 11, 22 } },	/* IEEE80211_MODE_TURBO_G (mixed b/g) */
  };
  
@@ -153,16 +156,13 @@
  /*
   * Mark the basic rates for the 11g rate table based on the
   * specified mode.  For 11b compatibility we mark only 11b
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_var.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_var.h	2007-07-23 01:48:44.622523064 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_var.h	2007-07-23 01:48:45.734586433 +0200
-@@ -592,6 +592,8 @@
- void ieee80211_build_countryie(struct ieee80211com *);
- int ieee80211_media_setup(struct ieee80211com *, struct ifmedia *, u_int32_t,
- 	ifm_change_cb_t, ifm_stat_cb_t);
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -708,6 +708,7 @@
+ void ieee80211_build_sc_ie(struct ieee80211com *);
+ void ieee80211_dfs_action(struct ieee80211com *);
+ void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
 +void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
-+
  
- /* Key update synchronization methods.  XXX should not be visible. */
- static __inline void
+ /*
+  * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/306-mib_intr_workaround.patch kamikaze_7.09/package/madwifi/patches/306-mib_intr_workaround.patch
--- kamikaze_7.09.orig/package/madwifi/patches/306-mib_intr_workaround.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/306-mib_intr_workaround.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,83 +0,0 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-08-01 11:07:47.882943145 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-08-01 11:41:11.781138794 +0200
-@@ -203,6 +203,7 @@
- static void ath_flushrecv(struct ath_softc *);
- static void ath_chan_change(struct ath_softc *, struct ieee80211_channel *);
- static void ath_calibrate(unsigned long);
-+static void ath_mib_enable(unsigned long);
- static int ath_newstate(struct ieee80211vap *, enum ieee80211_state, int);
- 
- static void ath_scan_start(struct ieee80211com *);
-@@ -660,6 +661,10 @@
- 	sc->sc_cal_ch.function = ath_calibrate;
- 	sc->sc_cal_ch.data = (unsigned long) dev;
- 
-+	init_timer(&sc->sc_mib_enable);
-+	sc->sc_mib_enable.function = ath_mib_enable;
-+	sc->sc_mib_enable.data = (unsigned long) sc;
-+
- #ifdef ATH_SUPERG_DYNTURBO
- 	init_timer(&sc->sc_dturbo_switch_mode);
- 	sc->sc_dturbo_switch_mode.function = ath_turbo_switch_mode;
-@@ -1751,16 +1756,19 @@
- 		if (status & HAL_INT_MIB) {
- 			sc->sc_stats.ast_mib++;
- 			/*
--			 * Disable interrupts until we service the MIB
--			 * interrupt; otherwise it will continue to fire.
--			 */
--			ath_hal_intrset(ah, 0);
--			/*
--			 * Let the HAL handle the event.  We assume it will
--			 * clear whatever condition caused the interrupt.
-+			 * When the card receives lots of PHY errors, the MIB
-+			 * interrupt will fire at a very rapid rate. We will use
-+			 * a timer to enforce at least 1 jiffy delay between
-+			 * MIB interrupts. This should be unproblematic, since
-+			 * the hardware will continue to update the counters in the
-+			 * mean time.
- 			 */
--			ath_hal_mibevent(ah, &sc->sc_halstats);
-+			sc->sc_imask &= ~HAL_INT_MIB;
- 			ath_hal_intrset(ah, sc->sc_imask);
-+			mod_timer(&sc->sc_mib_enable, jiffies + 1);
-+
-+			/* Let the HAL handle the event. */
-+			ath_hal_mibevent(ah, &sc->sc_halstats);
- 		}
- 	}
- 	if (needmark)
-@@ -8029,6 +8037,19 @@
- }
- 
- /*
-+ * Enable MIB interrupts again, after the ISR disabled them
-+ * to slow down the rate of PHY error reporting.
-+ */
-+static void
-+ath_mib_enable(unsigned long arg)
-+{
-+	struct ath_softc *sc = (struct ath_softc *) arg;
-+
-+	sc->sc_imask |= HAL_INT_MIB;
-+	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
-+}
-+
-+/*
-  * Periodically recalibrate the PHY to account
-  * for temperature/environment changes.
-  */
-Index: madwifi-ng-r2568-20070710/ath/if_athvar.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_athvar.h	2007-08-01 11:33:50.800008711 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_athvar.h	2007-08-01 11:34:33.202425088 +0200
-@@ -687,6 +687,7 @@
- 	struct ctl_table *sc_sysctls;
- 
- 	u_int16_t sc_reapcount;  		/* # of tx buffers reaped after net dev stopped */
-+	struct timer_list sc_mib_enable;
- 
- #ifdef ATH_REVERSE_ENGINEERING
- 	u_int8_t register_snapshot[MAX_REGISTER_ADDRESS];
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/309-micfail_detect.patch kamikaze_7.09/package/madwifi/patches/309-micfail_detect.patch
--- kamikaze_7.09.orig/package/madwifi/patches/309-micfail_detect.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/309-micfail_detect.patch	2008-06-19 17:34:17.000000000 +0200
@@ -1,16 +1,14 @@
-Index: madwifi-ng-r2568-20070710/ath/if_ath.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/ath/if_ath.c	2007-07-23 01:48:46.026603077 +0200
-+++ madwifi-ng-r2568-20070710/ath/if_ath.c	2007-07-23 01:48:46.310619260 +0200
-@@ -5632,6 +5632,7 @@
- 	u_int64_t rs_tsf;
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6446,6 +6446,7 @@
+ 	int type;
+ 	u_int phyerr;
  	u_int processed = 0, early_stop = 0;
- 	u_int rx_limit = dev->quota;
 +	u_int mic_fail = 0;
  
- 	/* Let the 802.11 layer know about the new noise floor */
- 	sc->sc_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
-@@ -5726,25 +5727,7 @@
+ 	DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n");
+ process_rx_again:
+@@ -6547,24 +6548,8 @@
  			}
  			if (rs->rs_status & HAL_RXERR_MIC) {
  				sc->sc_stats.ast_rx_badmic++;
@@ -19,7 +17,6 @@
 -				 * the 802.11 header for notification.
 -				 */
 -				/* XXX frag's and QoS frames */
--				len = rs->rs_datalen;
 -				if (len >= sizeof (struct ieee80211_frame)) {
 -					bus_dma_sync_single(sc->sc_bdev,
 -					    bf->bf_skbaddr, len,
@@ -27,17 +24,18 @@
 -#if 0
 -/* XXX revalidate MIC, lookup ni to find VAP */
 -					ieee80211_notify_michael_failure(ic,
--					    (struct ieee80211_frame *) skb->data,
+-					    (struct ieee80211_frame *)skb->data,
 -					    sc->sc_splitmic ?
 -					        rs->rs_keyix - 32 : rs->rs_keyix
 -					);
 -#endif
 -				}
 +				mic_fail = 1;
++				goto rx_accept;
  			}
  			/*
- 			 * Reject error frames if we have no vaps that 
-@@ -5809,8 +5792,9 @@
+ 			 * Reject error frames if we have no vaps that
+@@ -6603,8 +6588,9 @@
  		/*
  		 * Finished monitor mode handling, now reject
  		 * error frames before passing to other vaps
@@ -45,14 +43,13 @@
  		 */
 -		if (rs->rs_status != 0) {
 +		if (rs->rs_status & ~(HAL_RXERR_MIC | HAL_RXERR_DECRYPT)) {
- 			dev_kfree_skb(skb);
- 			skb = NULL;
+ 			ieee80211_dev_kfree_skb(&skb);
  			goto rx_next;
-@@ -5841,6 +5825,27 @@
- 				   sc->sc_hwmap[rs->rs_rate].ieeerate,
- 				   rs->rs_rssi);
+ 		}
+@@ -6612,6 +6598,26 @@
+ 		/* remove the CRC */
+ 		skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
  
-+		/* MIC failure. Drop the packet in any case */
 +		if (mic_fail) {
 +			/* Ignore control frames which are reported with mic error */
 +		    if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
@@ -71,15 +68,21 @@
 +			skb = NULL;
 +			mic_fail = 0;
 +			goto rx_next;
-+ 		}
++		}
 +
  		/*
- 		 * Locate the node for sender, track state, and then
- 		 * pass the (referenced) node up to the 802.11 layer
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_ccmp.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_crypto_ccmp.c	2007-07-23 01:48:42.870423216 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_ccmp.c	2007-07-23 01:48:46.310619260 +0200
+ 		 * From this point on we assume the frame is at least
+ 		 * as large as ieee80211_frame_min; verify that.
+@@ -6624,6 +6630,7 @@
+ 			goto rx_next;
+ 		}
+ 
++		/* MIC failure. Drop the packet in any case */
+ 		/*
+ 		 * Normal receive.
+ 		 */
+--- a/net80211/ieee80211_crypto_ccmp.c
++++ b/net80211/ieee80211_crypto_ccmp.c
 @@ -73,7 +73,7 @@
  static int ccmp_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
  static int ccmp_decap(struct ieee80211_key *, struct sk_buff *, int);
@@ -98,10 +101,8 @@
  {
  	return 1;
  }
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_crypto.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_crypto.h	2007-07-23 01:48:36.806077628 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_crypto.h	2007-07-23 01:48:46.326620171 +0200
+--- a/net80211/ieee80211_crypto.h
++++ b/net80211/ieee80211_crypto.h
 @@ -145,7 +145,7 @@
  	int (*ic_encap)(struct ieee80211_key *, struct sk_buff *, u_int8_t);
  	int (*ic_decap)(struct ieee80211_key *, struct sk_buff *, int);
@@ -124,10 +125,8 @@
  }
  
  /*
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_none.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_crypto_none.c	2007-07-23 01:48:36.810077857 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_none.c	2007-07-23 01:48:46.342621086 +0200
+--- a/net80211/ieee80211_crypto_none.c
++++ b/net80211/ieee80211_crypto_none.c
 @@ -52,7 +52,7 @@
  static int none_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
  static int none_decap(struct ieee80211_key *, struct sk_buff *, int);
@@ -146,10 +145,8 @@
  {
  	struct ieee80211vap *vap = k->wk_private;
  
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_tkip.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_crypto_tkip.c	2007-07-23 01:48:36.818078312 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_tkip.c	2007-07-23 01:48:46.362622225 +0200
+--- a/net80211/ieee80211_crypto_tkip.c
++++ b/net80211/ieee80211_crypto_tkip.c
 @@ -57,7 +57,7 @@
  static int tkip_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
  static int tkip_enmic(struct ieee80211_key *, struct sk_buff *, int);
@@ -177,10 +174,8 @@
  		struct ieee80211vap *vap = ctx->tc_vap;
  		u8 mic[IEEE80211_WEP_MICLEN];
  		u8 mic0[IEEE80211_WEP_MICLEN];
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_wep.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_crypto_wep.c	2007-07-23 01:48:36.826078768 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_crypto_wep.c	2007-07-23 01:48:46.402624504 +0200
+--- a/net80211/ieee80211_crypto_wep.c
++++ b/net80211/ieee80211_crypto_wep.c
 @@ -54,7 +54,7 @@
  static int wep_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
  static int wep_decap(struct ieee80211_key *, struct sk_buff *, int);
@@ -199,11 +194,9 @@
  {
  	return 1;
  }
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_input.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_input.c	2007-07-23 01:48:45.690583928 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_input.c	2007-07-23 01:48:46.406624734 +0200
-@@ -632,7 +632,7 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -669,7 +669,7 @@
  		 * Next strip any MSDU crypto bits.
  		 */
  		if (key != NULL &&
@@ -212,7 +205,7 @@
  			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  				ni->ni_macaddr, "data", "%s", "demic error");
  			IEEE80211_NODE_STAT(ni, rx_demicfail);
-@@ -3772,6 +3772,47 @@
+@@ -4293,6 +4293,47 @@
  }
  #endif
  
@@ -260,11 +253,9 @@
  #ifdef IEEE80211_DEBUG
  /*
   * Debugging support.
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_proto.h
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_proto.h	2007-07-23 01:48:36.838079452 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_proto.h	2007-07-23 01:48:46.438626555 +0200
-@@ -91,6 +91,7 @@
+--- a/net80211/ieee80211_proto.h
++++ b/net80211/ieee80211_proto.h
+@@ -90,6 +90,7 @@
  void ieee80211_set11gbasicrates(struct ieee80211_rateset *, enum ieee80211_phymode);
  enum ieee80211_phymode ieee80211_get11gbasicrates(struct ieee80211_rateset *);
  void ieee80211_send_pspoll(struct ieee80211_node *);
@@ -272,26 +263,22 @@
  
  /*
   * Return the size of the 802.11 header for a management or data frame.
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_linux.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_linux.c	2007-07-23 01:48:42.626409310 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_linux.c	2007-07-23 01:48:46.462627924 +0200
-@@ -291,8 +291,8 @@
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -337,8 +337,8 @@
  	/* TODO: needed parameters: count, keyid, key type, src address, TSC */
- 	snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
+ 	snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,
  		k->wk_keyix,
 -		IEEE80211_IS_MULTICAST(wh->i_addr1) ?  "broad" : "uni",
--		ether_sprintf(wh->i_addr1));
+-		MAC_ADDR(wh->i_addr1));
 +		IEEE80211_IS_MULTICAST(wh->i_addr2) ?  "broad" : "uni",
-+		ether_sprintf(wh->i_addr2));
++		MAC_ADDR(wh->i_addr2));
  	memset(&wrqu, 0, sizeof(wrqu));
  	wrqu.data.length = strlen(buf);
  	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_output.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_output.c	2007-07-23 01:48:36.854080363 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_output.c	2007-07-23 01:48:46.466628154 +0200
-@@ -1079,13 +1079,16 @@
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -1074,13 +1074,16 @@
  			cip = (struct ieee80211_cipher *) key->wk_cipher;
  			ciphdrsize = cip->ic_header;
  			tailsize += (cip->ic_trailer + cip->ic_miclen);
@@ -311,24 +298,22 @@
  
  		/*
  		 * Allocate sk_buff for each subsequent fragment; First fragment
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_node.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_node.c	2007-07-23 01:48:45.694584154 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_node.c	2007-07-23 01:48:46.590635219 +0200
-@@ -1891,11 +1891,13 @@
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -2264,11 +2264,13 @@
  	/* From this point onwards we can no longer find the node,
  	 * so no more references are generated
  	 */
 -	ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
 -	ieee80211_del_wds_node(nt, ni);
 -	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
--	_node_table_leave(nt, ni);
+-	node_table_leave_locked(nt, ni);
 -	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
 +	if (nt) {
 +		ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
 +		ieee80211_del_wds_node(nt, ni);
 +		IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
-+		_node_table_leave(nt, ni);
++		node_table_leave_locked(nt, ni);
 +		IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
 +	}
  
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/310-erp_beacon_check.patch kamikaze_7.09/package/madwifi/patches/310-erp_beacon_check.patch
--- kamikaze_7.09.orig/package/madwifi/patches/310-erp_beacon_check.patch	2007-09-20 10:54:59.000000000 +0200
+++ kamikaze_7.09/package/madwifi/patches/310-erp_beacon_check.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-Index: madwifi-ng-r2568-20070710/net80211/ieee80211_beacon.c
-===================================================================
---- madwifi-ng-r2568-20070710.orig/net80211/ieee80211_beacon.c	2007-07-23 01:48:42.278389477 +0200
-+++ madwifi-ng-r2568-20070710/net80211/ieee80211_beacon.c	2007-07-23 01:48:46.966656645 +0200
-@@ -512,7 +512,7 @@
- 			vap->iv_flags &= ~IEEE80211_F_XRUPDATE;
- 		}
- #endif
--		if (ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) {
-+		if ((ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) && (bo->bo_erp != NULL)) {
- 			(void) ieee80211_add_erp(bo->bo_erp, ic);
- 			ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
- 		}
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/310-noise_get.patch kamikaze_7.09/package/madwifi/patches/310-noise_get.patch
--- kamikaze_7.09.orig/package/madwifi/patches/310-noise_get.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/310-noise_get.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,55 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1695,8 +1695,6 @@
+ 	 * get to reality.  This value is used in monitor mode and by tools like
+ 	 * Wireshark and Kismet.
+ 	 */
+-	ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
+-
+ 	ATH_RXBUF_LOCK_IRQ(sc);
+ 	if (sc->sc_rxbufcur == NULL)
+ 		sc->sc_rxbufcur = STAILQ_FIRST(&sc->sc_rxbuf);
+@@ -8966,6 +8964,7 @@
+ 			sc->sc_curchan.channel);
+ 		sc->sc_stats.ast_per_calfail++;
+ 	}
++	ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
+ 
+ 	ath_hal_process_noisefloor(ah);
+ 	if (isIQdone == AH_TRUE) {
+@@ -9034,6 +9033,7 @@
+ 	struct ath_softc *sc = dev->priv;
+ 
+ 	(void) ath_chan_set(sc, ic->ic_curchan);
++	ic->ic_channoise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
+ 	/*
+ 	 * If we are returning to our bss channel then mark state
+ 	 * so the next recv'd beacon's TSF will be used to sync the
+@@ -9302,6 +9302,7 @@
+ 		}
+ 
+ 		ath_hal_process_noisefloor(ah);
++		ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
+ 		/*
+ 		 * Reset rssi stats; maybe not the best place...
+ 		 */
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -4358,6 +4358,7 @@
+ 	si->isi_state = ni->ni_flags;
+ 	si->isi_authmode = ni->ni_authmode;
+ 	si->isi_rssi = ic->ic_node_getrssi(ni);
++	si->isi_noise = ic->ic_channoise;
+ 	si->isi_capinfo = ni->ni_capinfo;
+ 	si->isi_athflags = ni->ni_ath_flags;
+ 	si->isi_erp = ni->ni_erp;
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -311,6 +311,7 @@
+ 	u_int16_t isi_state;		/* state flags */
+ 	u_int8_t isi_authmode;		/* authentication algorithm */
+ 	u_int8_t isi_rssi;
++	int8_t isi_noise;
+ 	u_int16_t isi_capinfo;		/* capabilities */
+ 	u_int8_t isi_athflags;		/* Atheros capabilities */
+ 	u_int8_t isi_erp;		/* ERP element */
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/311-bssid_alloc.patch kamikaze_7.09/package/madwifi/patches/311-bssid_alloc.patch
--- kamikaze_7.09.orig/package/madwifi/patches/311-bssid_alloc.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/311-bssid_alloc.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1354,7 +1354,7 @@
+ 		TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)
+ 			id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));
+ 
+-		for (id = 1; id < ath_maxvaps; id++) {
++		for (id = 0; id < ath_maxvaps; id++) {
+ 			/* get the first available slot */
+ 			if ((id_mask & (1 << id)) == 0) {
+ 				ATH_SET_VAP_BSSID(vap->iv_myaddr, id);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/312-erpupdate.patch kamikaze_7.09/package/madwifi/patches/312-erpupdate.patch
--- kamikaze_7.09.orig/package/madwifi/patches/312-erpupdate.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/312-erpupdate.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,68 @@
+--- a/net80211/ieee80211_beacon.c
++++ b/net80211/ieee80211_beacon.c
+@@ -542,10 +542,10 @@
+ 			vap->iv_flags &= ~IEEE80211_F_XRUPDATE;
+ 		}
+ #endif
+-		if ((ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) && 
++		if ((vap->iv_flags_ext & IEEE80211_FEXT_ERPUPDATE) &&
+ 				(bo->bo_erp != NULL)) {
+ 			(void)ieee80211_add_erp(bo->bo_erp, ic);
+-			ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
++			vap->iv_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
+ 		}
+ 	}
+ 	/* if it is a mode change beacon for dynamic turbo case */
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3431,9 +3431,12 @@
+ 			/* Assume no ERP IE == 11b AP */
+ 			if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+ 				!(ic->ic_flags & IEEE80211_F_USEPROT)) {
++				struct ieee80211vap *tmpvap;
+ 
+ 				ic->ic_flags |= IEEE80211_F_USEPROT;
+-				ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++				TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++					tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++				}
+ 			}
+ 		}
+ 
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -2025,8 +2025,12 @@
+ 		}
+ 
+ 		/* Update ERP element if this is first non ERP station */
+-		if (ic->ic_nonerpsta == 1)
+-			ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++		if (ic->ic_nonerpsta == 1) {
++			struct ieee80211vap *tmpvap;
++			TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++				tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++			}
++		}
+ 	} else
+ 		ni->ni_flags |= IEEE80211_NODE_ERP;
+ }
+@@ -2229,6 +2233,8 @@
+ 		IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
+ 			"non-ERP station leaves, count now %d", ic->ic_nonerpsta);
+ 		if (ic->ic_nonerpsta == 0) {
++			struct ieee80211vap *tmpvap;
++
+ 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
+ 				"%s: disable use of protection\n", __func__);
+ 			ic->ic_flags &= ~IEEE80211_F_USEPROT;
+@@ -2240,7 +2246,9 @@
+ 				ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
+ 				ic->ic_flags &= ~IEEE80211_F_USEBARKER;
+ 			}
+-			ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++			TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++				tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++			}
+ 		}
+ 	}
+ }
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/317-bmask.patch kamikaze_7.09/package/madwifi/patches/317-bmask.patch
--- kamikaze_7.09.orig/package/madwifi/patches/317-bmask.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/317-bmask.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,13 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8680,6 +8680,10 @@
+ 
+ 	sc->sc_rxbufcur = NULL;
+ 
++	/* configure bssid mask */
++	if (sc->sc_hasbmask)
++		ath_hal_setbssidmask(ah, sc->sc_bssidmask);
++
+ 	bf = STAILQ_FIRST(&sc->sc_rxbuf);
+ 	ath_hal_putrxbuf(ah, bf->bf_daddr);
+ 	ath_hal_rxena(ah);		/* enable recv descriptors */
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/323-dfs_optional.patch kamikaze_7.09/package/madwifi/patches/323-dfs_optional.patch
--- kamikaze_7.09.orig/package/madwifi/patches/323-dfs_optional.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/323-dfs_optional.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,38 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1774,17 +1774,14 @@
+ 			 * may have occurred in the intervening timeframe. */
+ 			bf->bf_channoise = ic->ic_channoise;
+ 
+-			if (rs->rs_status) {
+-				if ((HAL_RXERR_PHY == rs->rs_status) &&
+-				    (HAL_PHYERR_RADAR ==
+-				     (rs->rs_phyerr & 0x1f)) &&
+-				    (0 == (bf->bf_status &
+-					   ATH_BUFSTATUS_RADAR_DONE))) {
+-					check_for_radar = 1;
+-				}
+-				/* Skip past the error now */
++			if ((HAL_RXERR_PHY == rs->rs_status) &&
++			    (HAL_PHYERR_RADAR == (rs->rs_phyerr & 0x1f)) &&
++			    (0 == (bf->bf_status & ATH_BUFSTATUS_RADAR_DONE)) &&
++			    (ic->ic_flags & IEEE80211_F_DOTH))
++				check_for_radar = 1;
++
++			if (rs->rs_status) /* Skip past the error now */
+ 				continue;
+-			}
+ 
+ 			/* Prepare wireless header for examination */
+ 			bus_dma_sync_single(sc->sc_bdev, bf->bf_skbaddr,
+--- a/ath/if_ath_radar.c
++++ b/ath/if_ath_radar.c
+@@ -261,7 +261,7 @@
+ 		unsigned int new_rxfilt = old_rxfilt;
+ 
+ 		ath_hal_intrset(ah, old_ier & ~HAL_INT_GLOBAL);
+-		if (required) {
++		if ((required) && (ic->ic_flags & IEEE80211_F_DOTH)) {
+ 			new_radar |= AR5K_PHY_RADAR_ENABLE;
+ 			new_filter |= AR5K_AR5212_PHY_ERR_FIL_RADAR;
+ 			new_rxfilt |= (HAL_RX_FILTER_PHYERR | 
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/324-alignment.patch kamikaze_7.09/package/madwifi/patches/324-alignment.patch
--- kamikaze_7.09.orig/package/madwifi/patches/324-alignment.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/324-alignment.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,19 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1275,14 +1275,8 @@
+ 		eh->ether_type = ether_type;
+ 
+ 	if (!ALIGNED_POINTER(skb->data + sizeof(*eh), u_int32_t)) {
+-		struct sk_buff *tskb;
+-
+-		/* XXX: does this always work? */
+-		tskb = skb_copy(skb, GFP_ATOMIC);
+-		if (tskb)
+-			ieee80211_skb_copy_noderef(skb, tskb);
+-		ieee80211_dev_kfree_skb(&skb);
+-		skb = tskb;
++		memmove(skb->data - 2, skb->data, skb->len);
++		skb->data -= 2;
+ 	}
+ 	return skb;
+ }
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/325-channel_spam.patch kamikaze_7.09/package/madwifi/patches/325-channel_spam.patch
--- kamikaze_7.09.orig/package/madwifi/patches/325-channel_spam.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/325-channel_spam.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,28 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -9783,7 +9783,9 @@
+ 	/*
+ 	 * Convert HAL channels to ieee80211 ones.
+ 	 */
++#ifdef AR_DEBUG
+ 	IPRINTF(sc, "HAL returned %d channels.\n", nchan);
++#endif
+ 	for (i = 0; i < nchan; i++) {
+ 		HAL_CHANNEL *c = &chans[i];
+ 		struct ieee80211_channel *ichan = &ic->ic_channels[i];
+@@ -9810,6 +9812,7 @@
+ 		ic->ic_chan_non_occupy[i].tv_sec  = 0;
+ 		ic->ic_chan_non_occupy[i].tv_usec = 0;
+ 
++#ifdef AR_DEBUG
+ 		IPRINTF(sc, "Channel %3d (%4d MHz) Max Tx Power %d dBm%s "
+ 				"[%d hw %d reg] Flags%s%s%s%s%s%s%s%s%s%s%s%s%"
+ 				"s%s%s%s%s%s%s%s%s%s%s%s\n",
+@@ -9898,6 +9901,7 @@
+ 				(c->privFlags & 0x0080 ? 
+ 				 " PF & (1 << 7)" : "")
+ 				);
++#endif
+ 	}
+ 	ic->ic_nchans = nchan;
+ 	kfree(chans);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/327-queue.patch kamikaze_7.09/package/madwifi/patches/327-queue.patch
--- kamikaze_7.09.orig/package/madwifi/patches/327-queue.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/327-queue.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,40 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8431,8 +8431,6 @@
+ 	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+ 	local_irq_restore(flags);
+ 
+-	netif_wake_queue(dev);
+-
+ 	if (sc->sc_softled)
+ 		ath_led_event(sc, ATH_LED_TX);
+ }
+@@ -8479,8 +8477,6 @@
+ 	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+ 	local_irq_restore(flags);
+ 
+-	netif_wake_queue(dev);
+-
+ 	if (sc->sc_softled)
+ 		ath_led_event(sc, ATH_LED_TX);
+ }
+@@ -8513,8 +8509,6 @@
+ 	ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+ 	local_irq_restore(flags);
+ 
+-	netif_wake_queue(dev);
+-
+ 	if (sc->sc_softled)
+ 		ath_led_event(sc, ATH_LED_TX);
+ }
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1132,7 +1132,7 @@
+ 	    (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0) {
+ 		struct sk_buff *skb1 = NULL;
+ 
+-		if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
++		if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
+ 			/* Create a SKB for the BSS to send out. */
+ 			skb1 = skb_copy(skb, GFP_ATOMIC);
+ 			if (skb1)
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/330-beaconcal.patch kamikaze_7.09/package/madwifi/patches/330-beaconcal.patch
--- kamikaze_7.09.orig/package/madwifi/patches/330-beaconcal.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/330-beaconcal.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,164 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -397,6 +397,7 @@
+ static int maxvaps = -1;
+ static int outdoor = -1;
+ static int xchanmode = -1;
++static int beacon_cal = 1;
+ 
+ static const char *hal_status_desc[] = {
+ 	"No error",
+@@ -422,6 +423,7 @@
+ };
+ 
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
++MODULE_PARM(beacon_cal, "i");
+ MODULE_PARM(countrycode, "i");
+ MODULE_PARM(maxvaps, "i");
+ MODULE_PARM(outdoor, "i");
+@@ -434,6 +436,7 @@
+ MODULE_PARM(ratectl, "s");
+ #else
+ #include <linux/moduleparam.h>
++module_param(beacon_cal, int, 0600);
+ module_param(countrycode, int, 0600);
+ module_param(maxvaps, int, 0600);
+ module_param(outdoor, int, 0600);
+@@ -2598,7 +2601,8 @@
+ 		}
+ 		if (!sc->sc_invalid) {
+ 			del_timer_sync(&sc->sc_dfs_cac_timer);
+-			del_timer_sync(&sc->sc_cal_ch);
++			if (!sc->sc_beacon_cal)
++				del_timer_sync(&sc->sc_cal_ch);
+ 		}
+ 		ath_draintxq(sc);
+ 		if (!sc->sc_invalid) {
+@@ -2615,6 +2619,20 @@
+ 	return 0;
+ }
+ 
++static void ath_set_beacon_cal(struct ath_softc *sc, int val)
++{
++	if (sc->sc_beacon_cal == !!val)
++		return;
++
++	if (val) {
++		del_timer_sync(&sc->sc_cal_ch);
++	} else {
++		sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
++		add_timer(&sc->sc_cal_ch);
++	}
++	sc->sc_beacon_cal = !!val && beacon_cal;
++}
++
+ /*
+  * Stop the device, grabbing the top-level lock to protect
+  * against concurrent entry through ath_init (which can happen
+@@ -2740,6 +2758,12 @@
+ 	HAL_STATUS status;
+ 
+ 	/*
++	 * XXX: starting the calibration too early seems to lead to
++	 * problems with the beacons.
++	 */
++	sc->sc_lastcal = jiffies;
++
++	/*
+ 	 * Convert to a HAL channel description with the flags
+ 	 * constrained to reflect the current operating mode.
+ 	 */
+@@ -5145,6 +5169,8 @@
+ 			"Invoking ath_hal_txstart with sc_bhalq: %d\n",
+ 			sc->sc_bhalq);
+ 		ath_hal_txstart(ah, sc->sc_bhalq);
++		if (sc->sc_beacon_cal && (jiffies > sc->sc_lastcal + (ath_calinterval * HZ)))
++			ath_calibrate((unsigned long) sc->sc_dev);
+ 
+ 		sc->sc_stats.ast_be_xmit++;		/* XXX per-VAP? */
+ 	}
+@@ -5394,6 +5420,7 @@
+ 		ath_hal_beacontimers(ah, &bs);
+ 		sc->sc_imask |= HAL_INT_BMISS;
+ 		ath_hal_intrset(ah, sc->sc_imask);
++		ath_set_beacon_cal(sc, 0);
+ 	} else {
+ 		ath_hal_intrset(ah, 0);
+ 		if (reset_tsf)
+@@ -5405,8 +5432,11 @@
+ 			 */
+ 			intval |= HAL_BEACON_ENA;
+ 			sc->sc_imask |= HAL_INT_SWBA;
++			ath_set_beacon_cal(sc, 1);
+ 			ath_beaconq_config(sc);
+-		}
++		} else
++			ath_set_beacon_cal(sc, 0);
++
+ #ifdef ATH_SUPERG_DYNTURBO
+ 		ath_beacon_dturbo_config(vap, intval &
+ 				~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA));
+@@ -8870,6 +8900,9 @@
+ 			/* Enter DFS wait period */
+ 			mod_timer(&sc->sc_dfs_cac_timer,
+ 				jiffies + (sc->sc_dfs_cac_period * HZ));
++
++			/* This is a good time to start a calibration */
++			ath_set_beacon_cal(sc, 1);
+ 		}
+ 		/*
+ 		 * re configure beacons when it is a turbo mode switch.
+@@ -8979,8 +9012,11 @@
+ 		sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
+ 		isIQdone ? "done" : "not done");
+ 
+-	sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+-	add_timer(&sc->sc_cal_ch);
++	sc->sc_lastcal = jiffies;
++	if (!sc->sc_beacon_cal) {
++		sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
++		add_timer(&sc->sc_cal_ch);
++	}
+ }
+ 
+ static void
+@@ -9087,7 +9123,8 @@
+ 		ieee80211_state_name[vap->iv_state],
+ 		ieee80211_state_name[nstate]);
+ 
+-	del_timer(&sc->sc_cal_ch);		/* periodic calibration timer */
++	if (!sc->sc_beacon_cal)
++		del_timer(&sc->sc_cal_ch);		/* periodic calibration timer */
+ 
+ 	ath_hal_setledstate(ah, leds[nstate]);	/* set LED */
+ 	netif_stop_queue(dev);			/* before we do anything else */
+@@ -9312,7 +9349,8 @@
+ 				"VAP -> DFSWAIT_PENDING \n");
+ 			/* start calibration timer with a really small value 
+ 			 * 1/10 sec */
+-			mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
++			if (!sc->sc_beacon_cal)
++				mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
+ 			/* wake the receiver */
+ 			netif_wake_queue(dev);
+ 			/* don't do the other usual stuff... */
+@@ -9355,7 +9393,7 @@
+ 	error = avp->av_newstate(vap, nstate, arg);
+ 
+ 	/* Finally, start any timers. */
+-	if (nstate == IEEE80211_S_RUN) {
++	if (nstate == IEEE80211_S_RUN && !sc->sc_beacon_cal) {
+ 		/* start periodic recalibration timer */
+ 		mod_timer(&sc->sc_cal_ch, jiffies + (ath_calinterval * HZ));
+ 	}
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -778,6 +778,8 @@
+ 	struct ieee80211vap **sc_bslot;		/* beacon xmit slots */
+ 	int sc_bnext;				/* next slot for beacon xmit */
+ 
++	int sc_beacon_cal;			/* use beacon timer for calibration */
++	u_int64_t sc_lastcal;			/* last time the calibration was performed */
+ 	struct timer_list sc_cal_ch;		/* calibration timer */
+ 	HAL_NODE_STATS sc_halstats;		/* station-mode rssi stats */
+ 
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/331-memory_alloc.patch kamikaze_7.09/package/madwifi/patches/331-memory_alloc.patch
--- kamikaze_7.09.orig/package/madwifi/patches/331-memory_alloc.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/331-memory_alloc.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,36 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3318,17 +3318,18 @@
+ 	 * without affecting any other bridge ports. */
+ 	if (skb_cloned(skb)) {
+ 		/* Remember the original SKB so we can free up our references */
+-		struct sk_buff *skb_orig = skb;
+-		skb = skb_copy(skb, GFP_ATOMIC);
+-		if (skb == NULL) {
++		struct sk_buff *skb_new;
++		skb_new = skb_copy(skb, GFP_ATOMIC);
++		if (skb_new == NULL) {
+ 			DPRINTF(sc, ATH_DEBUG_XMIT,
+ 				"Dropping; skb_copy failure.\n");
+ 			/* No free RAM, do not requeue! */
+ 			goto hardstart_fail;
+ 		}
+-		ieee80211_skb_copy_noderef(skb_orig, skb);
+-		ieee80211_dev_kfree_skb(&skb_orig);
+-	} 
++		ieee80211_skb_copy_noderef(skb, skb_new);
++		ieee80211_dev_kfree_skb(&skb);
++		skb = skb_new;
++	}
+ 	eh = (struct ether_header *)skb->data;
+ 
+ #ifdef ATH_SUPERG_FF
+@@ -3599,6 +3600,8 @@
+ 	sc->sc_stats.ast_tx_mgmt++;
+ 	return 0;
+ bad:
++	if (skb)
++		ieee80211_dev_kfree_skb(&skb);
+ 	ath_return_txbuf(sc, &bf);
+ 	return error;
+ }
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/332-reset_beacons.patch kamikaze_7.09/package/madwifi/patches/332-reset_beacons.patch
--- kamikaze_7.09.orig/package/madwifi/patches/332-reset_beacons.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/332-reset_beacons.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8911,7 +8911,7 @@
+ 		 * re configure beacons when it is a turbo mode switch.
+ 		 * HW seems to turn off beacons during turbo mode switch.
+ 		 */
+-		if (sc->sc_beacons && tswitch && !sc->sc_dfs_cac)
++		if (sc->sc_beacons && !sc->sc_dfs_cac)
+ 			ath_beacon_config(sc, NULL);
+ 		/*
+ 		 * Re-enable interrupts.
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/333-apscan_mode.patch kamikaze_7.09/package/madwifi/patches/333-apscan_mode.patch
--- kamikaze_7.09.orig/package/madwifi/patches/333-apscan_mode.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/333-apscan_mode.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,15 @@
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -781,12 +781,6 @@
+ 				/* break the loop as the subsequent chans won't be 
+ 				 * better */
+ 				break;
+-
+-			if (!IEEE80211_ARE_CHANS_SAME_MODE(c->chan,
+-				ic->ic_bsschan))
+-				/* break the loop as the subsequent chans won't be 
+-				 * better */
+-				break;
+ 		}
+ 
+ 		if (sta_assoc != 0) {
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/334-input.patch kamikaze_7.09/package/madwifi/patches/334-input.patch
--- kamikaze_7.09.orig/package/madwifi/patches/334-input.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/334-input.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,12 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -950,6 +950,9 @@
+ 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ 		struct sk_buff *skb1;
+ 
++		if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
++			continue;
++
+ 		if (TAILQ_NEXT(vap, iv_next) != NULL) {
+ 			skb1 = skb_copy(skb, GFP_ATOMIC);
+ 			if (skb1 == NULL) {
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/340-maxrate.patch kamikaze_7.09/package/madwifi/patches/340-maxrate.patch
--- kamikaze_7.09.orig/package/madwifi/patches/340-maxrate.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/340-maxrate.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,98 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1307,6 +1307,7 @@
+ 	vap->iv_key_set = ath_key_set;
+ 	vap->iv_key_update_begin = ath_key_update_begin;
+ 	vap->iv_key_update_end = ath_key_update_end;
++	vap->iv_maxrateindex = 0;
+ 	if (sc->sc_default_ieee80211_debug) {
+ 		/* User specified defaults for new VAPs were provided, so
+ 		 * use those (only). */
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -622,8 +622,12 @@
+ 			return;
+ 		}
+ 		sn->static_rate_ndx = -1;
++		if (vap->iv_maxrateindex == 0 || ni->ni_rates.rs_nrates <= 0
++		    || vap->iv_maxrateindex > ni->ni_rates.rs_nrates)
++			sn->num_rates = ni->ni_rates.rs_nrates;
++		else
++			sn->num_rates = vap->iv_maxrateindex;
+ 
+-		sn->num_rates = ni->ni_rates.rs_nrates;
+ 		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
+ 			sn->rs_rateattempts 	[x] = 0;
+ 			sn->rs_thisprob 	[x] = 0;
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -835,7 +835,12 @@
+ 	}
+ 	sn->static_rate_ndx = -1;
+ 
+-	sn->num_rates = ni->ni_rates.rs_nrates;
++	if (vap->iv_maxrateindex == 0 || ni->ni_rates.rs_nrates <= 0
++	    || vap->iv_maxrateindex > ni->ni_rates.rs_nrates)
++		sn->num_rates = ni->ni_rates.rs_nrates;
++	else
++		sn->num_rates = vap->iv_maxrateindex;
++
+ 	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
+ 		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+ 		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -641,6 +641,7 @@
+ 							   FCC requires 30m, so that is the default. */
+ 	IEEE80211_PARAM_BEACON_MISS_THRESH	= 73,	/* Beacon miss threshold (in beacons) */
+ 	IEEE80211_PARAM_BEACON_MISS_THRESH_MS	= 74,	/* Beacon miss threshold (in ms) */
++	IEEE80211_PARAM_MAXRATE			= 75,	/* Maximum rate (by table index) */
+ };
+ 
+ #define	SIOCG80211STATS			(SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -281,6 +281,7 @@
+ 	struct ieee80211_spy iv_spy;         		/* IWSPY support */
+ 	struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
+ 	u_int32_t app_filter;				/* filters which management frames are forwarded to app */
++	int iv_maxrateindex;
+ };
+ 
+ /* Debug functions need the defintion of struct ieee80211vap because iv_debug 
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2839,6 +2839,12 @@
+ 		else
+ 			ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
+ 		break;
++	case IEEE80211_PARAM_MAXRATE:
++		if (value > 0)
++			vap->iv_maxrateindex = value;
++		else
++			vap->iv_maxrateindex = 0;
++		break;
+ #ifdef ATH_REVERSE_ENGINEERING
+ 	case IEEE80211_PARAM_DUMPREGS:
+ 		ieee80211_dump_registers(dev, info, w, extra);
+@@ -3174,6 +3180,9 @@
+ 		else
+ 			param[0] = 0;
+ 		break;
++	case IEEE80211_PARAM_MAXRATE:
++		param[0] = vap->iv_maxrateindex;
++		break;
+ 	default:
+ 		return -EOPNOTSUPP;
+ 	}
+@@ -5610,6 +5619,10 @@
+ 	  0, IW_PRIV_TYPE_APPIEBUF, "getiebuf" },
+ 	{ IEEE80211_IOCTL_FILTERFRAME,
+ 	  IW_PRIV_TYPE_FILTER , 0, "setfilter" },
++	{IEEE80211_PARAM_MAXRATE,
++	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxrate"},
++	{IEEE80211_PARAM_MAXRATE,
++	 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxrate"},
+ 
+ #ifdef ATH_REVERSE_ENGINEERING
+ 	/*
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/341-minrate.patch kamikaze_7.09/package/madwifi/patches/341-minrate.patch
--- kamikaze_7.09.orig/package/madwifi/patches/341-minrate.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/341-minrate.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,114 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1308,6 +1308,7 @@
+ 	vap->iv_key_update_begin = ath_key_update_begin;
+ 	vap->iv_key_update_end = ath_key_update_end;
+ 	vap->iv_maxrateindex = 0;
++	vap->iv_minrateindex = 0;
+ 	if (sc->sc_default_ieee80211_debug) {
+ 		/* User specified defaults for new VAPs were provided, so
+ 		 * use those (only). */
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -638,9 +638,15 @@
+ 			sn->rs_succ_hist	[x] = 0;
+ 			sn->rs_att_hist 	[x] = 0;
+ 			sn->rs_this_tp 		[x] = 0;
+-
++			if (vap->iv_minrateindex && vap->iv_minrateindex<ni->ni_rates.rs_nrates)
++			{
++			int idx = vap->iv_minrateindex; 
++			sn->rates[x].rate = ni->ni_rates.rs_rates[idx] & IEEE80211_RATE_VAL;
++			sn->rates[x].rix = sc->sc_rixmap[sn->rates[idx].rate];
++			}else{
+ 			sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+ 			sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
++			}
+ 			if (sn->rates[x].rix == 0xff) {
+ 				DPRINTF(sc, "%s: %s ignore bogus rix at %d\n",
+ 					dev_info, __func__, x);
+@@ -649,7 +655,7 @@
+ 			sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
+ 			sn->rates[x].shortPreambleRateCode =
+ 				rt->info[sn->rates[x].rix].rateCode |
+-				rt->info[sn->rates[x].rix].shortPreamble;
++				rt->info[sn->rates[x].rix].shortPreamble;			
+ 		}
+ 
+ 		ath_fill_sample_table(sn);
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -842,8 +842,15 @@
+ 		sn->num_rates = vap->iv_maxrateindex;
+ 
+ 	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
+-		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+-		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
++		if (vap->iv_minrateindex && vap->iv_minrateindex<ni->ni_rates.rs_nrates)
++			{
++			int idx = vap->iv_minrateindex; 
++			sn->rates[x].rate = ni->ni_rates.rs_rates[idx] & IEEE80211_RATE_VAL;
++			sn->rates[x].rix = sc->sc_rixmap[sn->rates[idx].rate];
++			}else{
++			sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
++			sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
++			}
+ 		if (sn->rates[x].rix == 0xff) {
+ 			DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %u\n",
+ 				dev_info, __func__, x);
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -642,6 +642,7 @@
+ 	IEEE80211_PARAM_BEACON_MISS_THRESH	= 73,	/* Beacon miss threshold (in beacons) */
+ 	IEEE80211_PARAM_BEACON_MISS_THRESH_MS	= 74,	/* Beacon miss threshold (in ms) */
+ 	IEEE80211_PARAM_MAXRATE			= 75,	/* Maximum rate (by table index) */
++	IEEE80211_PARAM_MINRATE			= 76,	/* Maximum rate (by table index) */
+ };
+ 
+ #define	SIOCG80211STATS			(SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -282,6 +282,7 @@
+ 	struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
+ 	u_int32_t app_filter;				/* filters which management frames are forwarded to app */
+ 	int iv_maxrateindex;
++	int iv_minrateindex;
+ };
+ 
+ /* Debug functions need the defintion of struct ieee80211vap because iv_debug 
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2845,6 +2845,12 @@
+ 		else
+ 			vap->iv_maxrateindex = 0;
+ 		break;
++	case IEEE80211_PARAM_MINRATE:
++		if (value > 0)
++			vap->iv_minrateindex = value;
++		else
++			vap->iv_minrateindex = 0;
++		break;
+ #ifdef ATH_REVERSE_ENGINEERING
+ 	case IEEE80211_PARAM_DUMPREGS:
+ 		ieee80211_dump_registers(dev, info, w, extra);
+@@ -3183,6 +3189,9 @@
+ 	case IEEE80211_PARAM_MAXRATE:
+ 		param[0] = vap->iv_maxrateindex;
+ 		break;
++	case IEEE80211_PARAM_MINRATE:
++		param[0] = vap->iv_minrateindex;
++		break;
+ 	default:
+ 		return -EOPNOTSUPP;
+ 	}
+@@ -5623,6 +5632,10 @@
+ 	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxrate"},
+ 	{IEEE80211_PARAM_MAXRATE,
+ 	 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxrate"},
++	{IEEE80211_PARAM_MINRATE,
++	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
++	{IEEE80211_PARAM_MINRATE,
++	 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
+ 
+ #ifdef ATH_REVERSE_ENGINEERING
+ 	/*
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/342-performance.patch kamikaze_7.09/package/madwifi/patches/342-performance.patch
--- kamikaze_7.09.orig/package/madwifi/patches/342-performance.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/342-performance.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,263 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3237,7 +3237,6 @@
+ 	struct ath_softc *sc = dev->priv;
+ 	struct ieee80211_node *ni = NULL;
+ 	struct ath_buf *bf = NULL;
+-	struct ether_header *eh;
+ 	ath_bufhead bf_head;
+ 	struct ath_buf *tbf, *tempbf;
+ 	struct sk_buff *tskb;
+@@ -3249,6 +3248,7 @@
+ 	*/
+ 	int requeue = 0;
+ #ifdef ATH_SUPERG_FF
++	struct ether_header *eh;
+ 	unsigned int pktlen;
+ 	struct ieee80211com *ic = &sc->sc_ic;
+ 	struct ath_node *an;
+@@ -3314,27 +3314,9 @@
+ 		requeue = 1;
+ 		goto hardstart_fail;
+ 	}
+-#endif
+ 
+-	/* If the skb data is shared, we will copy it so we can strip padding
+-	 * without affecting any other bridge ports. */
+-	if (skb_cloned(skb)) {
+-		/* Remember the original SKB so we can free up our references */
+-		struct sk_buff *skb_new;
+-		skb_new = skb_copy(skb, GFP_ATOMIC);
+-		if (skb_new == NULL) {
+-			DPRINTF(sc, ATH_DEBUG_XMIT,
+-				"Dropping; skb_copy failure.\n");
+-			/* No free RAM, do not requeue! */
+-			goto hardstart_fail;
+-		}
+-		ieee80211_skb_copy_noderef(skb, skb_new);
+-		ieee80211_dev_kfree_skb(&skb);
+-		skb = skb_new;
+-	}
+ 	eh = (struct ether_header *)skb->data;
+ 
+-#ifdef ATH_SUPERG_FF
+ 	/* NB: use this lock to protect an->an_tx_ffbuf (and txq->axq_stageq)
+ 	 *     in athff_can_aggregate() call too. */
+ 	ATH_TXQ_LOCK_IRQ(txq);
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -283,7 +283,7 @@
+ 	 * normal vap. */
+ 	if (vap->iv_xrvap && (ni == vap->iv_bss) &&
+ 	    vap->iv_xrvap->iv_sta_assoc) {
+-		struct sk_buff *skb1 = skb_copy(skb, GFP_ATOMIC);
++		struct sk_buff *skb1 = skb_clone(skb, GFP_ATOMIC);
+ 		if (skb1) {
+ 			memset(SKB_CB(skb1), 0, sizeof(struct ieee80211_cb));
+ #ifdef IEEE80211_DEBUG_REFCNT
+@@ -566,7 +566,7 @@
+ 	struct ieee80211_key *key, struct sk_buff *skb, int ismulticast)
+ {
+ 	/* XXX pre-calculate per node? */
+-	int need_headroom = LLC_SNAPFRAMELEN + hdrsize + IEEE80211_ADDR_LEN;
++	int need_headroom = LLC_SNAPFRAMELEN + hdrsize;
+ 	int need_tailroom = 0;
+ #ifdef ATH_SUPERG_FF
+ 	int isff = ATH_FF_MAGIC_PRESENT(skb);
+@@ -608,109 +608,56 @@
+ 				need_tailroom += cip->ic_miclen;
+ 	}
+ 
+-	if (skb_shared(skb)) {
+-		/* Take our own reference to the node in the clone */
+-		ieee80211_ref_node(SKB_CB(skb)->ni);
+-		/* Unshare the node, decrementing users in the old skb */
+-		skb = skb_unshare(skb, GFP_ATOMIC);
++	need_headroom -= skb_headroom(skb);
++	if (isff)
++		need_tailroom -= skb_tailroom(skb2);
++	else
++		need_tailroom -= skb_tailroom(skb);
++
++	if (need_headroom < 0)
++		need_headroom = 0;
++	if (need_tailroom < 0)
++		need_tailroom = 0;
++
++	if (skb_cloned(skb) || (need_headroom > 0) ||
++		(!isff && (need_tailroom > 0))) {
++
++		if (pskb_expand_head(skb, need_headroom, need_tailroom, GFP_ATOMIC)) {
++			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
++				"%s: cannot expand storage (tail)\n", __func__);
++			goto error;
++		}
+ 	}
+ 
+ #ifdef ATH_SUPERG_FF
+ 	if (isff) {
+-		if (skb == NULL) {
+-			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-				"%s: cannot unshare for encapsulation\n",
+-				__func__);
+-			vap->iv_stats.is_tx_nobuf++;
+-			ieee80211_dev_kfree_skb(&skb2);
+-
+-			return NULL;
+-		}
++		inter_headroom -= skb_headroom(skb2);
++		if (inter_headroom < 0)
++			inter_headroom = 0;
++		if ((skb_cloned(skb2) ||
++			(inter_headroom > 0) || (need_tailroom > 0))) {
+ 
+-		/* first skb header */
+-		if (skb_headroom(skb) < need_headroom) {
+-			struct sk_buff *tmp = skb;
+-			skb = skb_realloc_headroom(skb, need_headroom);
+-			if (skb == NULL) {
++			if (pskb_expand_head(skb2, inter_headroom,
++				need_tailroom, GFP_ATOMIC)) {
+ 				IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-					"%s: cannot expand storage (head1)\n",
+-					__func__);
+-				vap->iv_stats.is_tx_nobuf++;
+-				ieee80211_dev_kfree_skb(&skb2);
+-				return NULL;
+-			} else
+-				ieee80211_skb_copy_noderef(tmp, skb);
+-			ieee80211_dev_kfree_skb(&tmp);
+-			/* NB: cb[] area was copied, but not next ptr. must do that
+-			 *     prior to return on success. */
+-		}
+-
+-		/* second skb with header and tail adjustments possible */
+-		if (skb_tailroom(skb2) < need_tailroom) {
+-			int n = 0;
+-			if (inter_headroom > skb_headroom(skb2))
+-				n = inter_headroom - skb_headroom(skb2);
+-			if (pskb_expand_head(skb2, n,
+-			    need_tailroom - skb_tailroom(skb2), GFP_ATOMIC)) {
+-				ieee80211_dev_kfree_skb(&skb2);
+-				IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-					"%s: cannot expand storage (tail2)\n",
+-					__func__);
+-				vap->iv_stats.is_tx_nobuf++;
+-				/* this shouldn't happen, but don't send first ff either */
+-				ieee80211_dev_kfree_skb(&skb);
++					"%s: cannot expand storage (tail)\n", __func__);
++				goto error;
+ 			}
+-		} else if (skb_headroom(skb2) < inter_headroom) {
+-			struct sk_buff *tmp = skb2;
+-
+-			skb2 = skb_realloc_headroom(skb2, inter_headroom);
+-			if (skb2 == NULL) {
+-				IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-					"%s: cannot expand storage (head2)\n",
+-					__func__);
+-				vap->iv_stats.is_tx_nobuf++;
+-				/* this shouldn't happen, but don't send first ff either */
+-				ieee80211_dev_kfree_skb(&skb);
+-				skb = NULL;
+-			} else
+-				ieee80211_skb_copy_noderef(tmp, skb);
+-			ieee80211_dev_kfree_skb(&tmp);
+ 		}
+-		if (skb) {
+-			skb->next = skb2;
+-		}
+-		return skb;
++		skb->next = skb2;
+ 	}
+ #endif /* ATH_SUPERG_FF */
+-	if (skb == NULL) {
+-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-			"%s: cannot unshare for encapsulation\n", __func__);
+-		vap->iv_stats.is_tx_nobuf++;
+-	} else if (skb_tailroom(skb) < need_tailroom) {
+-		int n = 0;
+-		if (need_headroom > skb_headroom(skb))
+-			n = need_headroom - skb_headroom(skb);
+-		if (pskb_expand_head(skb, n, need_tailroom - 
+-					skb_tailroom(skb), GFP_ATOMIC)) {
+-			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-				"%s: cannot expand storage (tail)\n", __func__);
+-			vap->iv_stats.is_tx_nobuf++;
+-			ieee80211_dev_kfree_skb(&skb);
+-		}
+-	} else if (skb_headroom(skb) < need_headroom) {
+-		struct sk_buff *tmp = skb;
+-		skb = skb_realloc_headroom(skb, need_headroom);
+-		/* Increment reference count after copy */
+-		if (skb == NULL) {
+-			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-				"%s: cannot expand storage (head)\n", __func__);
+-			vap->iv_stats.is_tx_nobuf++;
+-		} else
+-			ieee80211_skb_copy_noderef(tmp, skb);
+-		ieee80211_dev_kfree_skb(&tmp);
+-	}
+ 
+ 	return skb;
++
++error:
++	vap->iv_stats.is_tx_nobuf++;
++	ieee80211_dev_kfree_skb(&skb);
++#ifdef ATH_SUPERG_FF
++	if (skb2)
++		ieee80211_dev_kfree_skb(&skb2);
++#endif
++	return NULL;
+ }
+ 
+ #define	KEY_UNDEFINED(k)	((k).wk_cipher == &ieee80211_cipher_none)
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -204,7 +204,6 @@
+ 	struct ieee80211_frame *wh;
+ 	struct ieee80211_key *key;
+ 	struct ether_header *eh;
+-	struct sk_buff *skb2;
+ #ifdef ATH_SUPERG_FF
+ 	struct llc *llc;
+ #endif
+@@ -244,20 +243,6 @@
+ 		vap->iv_stats.is_rx_tooshort++;
+ 		goto out;
+ 	}
+-	/* Clone the SKB... we assume somewhere in this driver that we 'own'
+-	 * the skbuff passed into hard start and we do a lot of messing with it
+-	 * but bridges under some cases will not clone for the first pass of skb
+-	 * to a bridge port, but will then clone for subsequent ones.  This is 
+-	 * odd behavior but it means that if we have trashed the skb we are given
+-	 * then other ports get clones of the residual garbage.
+-	 */
+-	if ((skb2 = skb_copy(skb, GFP_ATOMIC)) == NULL) {
+-		vap->iv_devstats.tx_dropped++;
+-		goto out;
+-	}
+-	ieee80211_skb_copy_noderef(skb, skb2);
+-	ieee80211_dev_kfree_skb(&skb);
+-	skb = skb2;
+ 
+ 	/*
+ 	 * Bit of a cheat here, we use a pointer for a 3-address
+@@ -738,7 +723,7 @@
+ 			/* ether_type must be length as FF frames are always LLC/SNAP encap'd */ 
+ 			frame_len = ntohs(eh_tmp->ether_type); 
+ 
+-			skb1 = skb_copy(skb, GFP_ATOMIC);
++			skb1 = skb_clone(skb, GFP_ATOMIC);
+ 			if (skb1 == NULL)
+ 				goto err;
+ 			ieee80211_skb_copy_noderef(skb, skb1);
+@@ -1137,7 +1122,7 @@
+ 
+ 		if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
+ 			/* Create a SKB for the BSS to send out. */
+-			skb1 = skb_copy(skb, GFP_ATOMIC);
++			skb1 = skb_clone(skb, GFP_ATOMIC);
+ 			if (skb1)
+ 				SKB_CB(skb1)->ni = ieee80211_ref_node(vap->iv_bss); 
+ 		}
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/343-txqueue_races.patch kamikaze_7.09/package/madwifi/patches/343-txqueue_races.patch
--- kamikaze_7.09.orig/package/madwifi/patches/343-txqueue_races.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/343-txqueue_races.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,34 @@
+Merged from madwifi trunk r3551, r3552
+
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8244,6 +8244,17 @@
+ 			goto bf_fail;
+ 		}
+ 
++		/* We make sure we don't remove the TX descriptor on
++		 * which the HW is pointing since it contains the
++		 * ds_link field, except if this is the last TX
++		 * descriptor in the queue */
++
++		if ((txq->axq_depth > 1) &&
++		    (bf->bf_daddr == ath_hal_gettxbuf(ah, txq->axq_qnum))) {
++			ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
++			goto bf_fail;
++		}
++
+ 		ATH_TXQ_REMOVE_HEAD(txq, bf_list);
+ 		ATH_TXQ_UNLOCK_IRQ(txq);
+ 
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -586,7 +586,8 @@
+ } while (0)
+ #define ATH_TXQ_REMOVE_HEAD(_tq, _field) do { \
+ 	STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
+-	(_tq)->axq_depth--; \
++	if (--(_tq)->axq_depth <= 0) \
++		(_tq)->axq_link = NULL; \
+ } while (0)
+ /* move buffers from MCASTQ to CABQ */
+ #define ATH_TXQ_MOVE_MCASTQ(_tqs,_tqd) do { \
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/344-minstrel_failcnt.patch kamikaze_7.09/package/madwifi/patches/344-minstrel_failcnt.patch
--- kamikaze_7.09.orig/package/madwifi/patches/344-minstrel_failcnt.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/344-minstrel_failcnt.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -475,7 +475,7 @@
+ 		/* 'tries' is the total number of times we have endeavoured to
+ 		 * send this packet, and is a sum of the #attempts at each
+ 		 * level in the multi-rate retry chain */
+-		tries = ts->ts_shortretry + ts->ts_longretry + 1;
++		tries = ts->ts_longretry + 1;
+ 
+ 		if (sn->num_rates <= 0) {
+ 			DPRINTF(sc, "%s: " MAC_FMT " %s no rates yet\n", dev_info,
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/345-minstrel_sampling.patch kamikaze_7.09/package/madwifi/patches/345-minstrel_sampling.patch
--- kamikaze_7.09.orig/package/madwifi/patches/345-minstrel_sampling.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/345-minstrel_sampling.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,80 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8094,6 +8094,7 @@
+ 		ath_hal_setupxtxdesc(sc->sc_ah, ds, mrr.rate1, mrr.retries1,
+ 				     mrr.rate2, mrr.retries2,
+ 				     mrr.rate3, mrr.retries3);
++		bf->rcflags = mrr.privflags;
+ 	}
+ 
+ #ifndef ATH_SUPERG_FF
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -446,6 +446,7 @@
+ 	u_int16_t bf_flags;				/* tx descriptor flags */
+ 	u_int64_t bf_tsf;
+ 	int16_t bf_channoise;
++	unsigned int rcflags;
+ #ifdef ATH_SUPERG_FF
+ 	/* XXX: combine this with bf_skbaddr if it ever changes to accommodate
+ 	 *      multiple segments.
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -333,15 +333,19 @@
+ 		if (sn->static_rate_ndx >= 0) {
+ 			    ndx = sn->static_rate_ndx;
+ 		} else {
++			int delta;
+ 			sn->packet_count++;
+ 			sn->random_n = (sn->a * sn->random_n) + sn->b;
+ 			offset = sn->random_n & 0xf;
+-			if ((((100 * sn->sample_count) / (sn->sample_count + sn->packet_count)) < ath_lookaround_rate) && (offset < 2)) {
++			delta = (sn->packet_count * ath_lookaround_rate / 100) - sn->sample_count;
++			if ((delta > 0) && (offset < 2)) {
+ 				sn->sample_count++;
+ 				sn->is_sampling = 1;
+ 				if (sn->packet_count >= 10000) {
+ 					sn->sample_count = 0;
+ 					sn->packet_count = 0;
++				} else if (delta > sn->num_rates * 2) {
++					sn->sample_count += ((delta - sn->num_rates * 2) * ath_lookaround_rate) / 100;
+ 				}
+ 
+ 				/* Don't look for slowest rate (i.e. slowest
+@@ -398,11 +402,14 @@
+ 		if (sn->num_rates <= 0)
+ 			return;
+ 
++		mrr->privflags = sn->is_sampling;
+ 		if (sn->is_sampling) {
+ 			sn->is_sampling = 0;
+-			if (sn->rs_sample_rate_slower)
++			if (sn->rs_sample_rate_slower) {
+ 				rc1 = sn->rs_sample_rate;
+-			else
++				if (sn->sample_count > 0)
++					sn->sample_count--;
++			} else
+ 				rc1 = sn->max_tp_rate;
+ 		} else {
+ 			rc1 = sn->max_tp_rate2;
+@@ -525,6 +532,9 @@
+ 		if (tries <= tries1)
+ 			return;
+ 
++		if (bf->rcflags)
++			sn->sample_count++;
++
+ 		if  (tries2 < 0)
+ 			return;
+ 		tries = tries - tries1;
+--- a/net80211/ieee80211_rate.h
++++ b/net80211/ieee80211_rate.h
+@@ -87,6 +87,7 @@
+ 	int retries2;
+ 	int rate3;
+ 	int retries3;
++	int privflags;
+ };
+ 
+ struct ieee80211_rate_ops {
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/346-protmode_trig.patch kamikaze_7.09/package/madwifi/patches/346-protmode_trig.patch
--- kamikaze_7.09.orig/package/madwifi/patches/346-protmode_trig.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/346-protmode_trig.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,135 @@
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -333,7 +333,9 @@
+ 			IEEE80211_MS_TO_TU(IEEE80211_BMISSTHRESH_DEFAULT_MS), 
+ 			ic->ic_lintval), ic->ic_lintval);
+ 	}
+-		
++	ic->ic_protmode_timeout = IEEE80211_PROTMODE_TIMEOUT;
++	ic->ic_protmode_rssi = IEEE80211_PROTMODE_RSSITHR;
++
+ 	IEEE80211_LOCK_INIT(ic, "ieee80211com");
+ 	IEEE80211_VAPS_LOCK_INIT(ic, "ieee80211com_vaps");
+ 	TAILQ_INIT(&ic->ic_vaps);
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3411,14 +3411,18 @@
+ 			IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
+ 
+ 			/* Assume no ERP IE == 11b AP */
+-			if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+-				!(ic->ic_flags & IEEE80211_F_USEPROT)) {
++			if ((!has_erp || (has_erp &&
++				(scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
++				(rssi > ic->ic_protmode_rssi)) {
+ 				struct ieee80211vap *tmpvap;
+ 
+-				ic->ic_flags |= IEEE80211_F_USEPROT;
+-				TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+-					tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++				if (!(ic->ic_flags & IEEE80211_F_USEPROT)) {
++					ic->ic_flags |= IEEE80211_F_USEPROT;
++					TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++						tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++					}
+ 				}
++				ic->ic_protmode_lasttrig = jiffies;
+ 			}
+ 		}
+ 
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -643,6 +643,8 @@
+ 	IEEE80211_PARAM_BEACON_MISS_THRESH_MS	= 74,	/* Beacon miss threshold (in ms) */
+ 	IEEE80211_PARAM_MAXRATE			= 75,	/* Maximum rate (by table index) */
+ 	IEEE80211_PARAM_MINRATE			= 76,	/* Maximum rate (by table index) */
++	IEEE80211_PARAM_PROTMODE_RSSI		= 77,	/* RSSI Threshold for enabling protection mode */
++	IEEE80211_PARAM_PROTMODE_TIMEOUT	= 78,	/* Timeout for expiring protection mode */
+ };
+ 
+ #define	SIOCG80211STATS			(SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -128,6 +128,9 @@
+ 
+ #define	IEEE80211_APPIE_MAX	1024
+ 
++#define IEEE80211_PROTMODE_RSSITHR	15	/* default rssi threshold for protection mode trigger */
++#define IEEE80211_PROTMODE_TIMEOUT	30	/* timeout for keeping protection mode alive */
++
+ #define IEEE80211_PWRCONSTRAINT_VAL(ic) \
+ 	(((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \
+ 	    (ic)->ic_bsschan->ic_maxregpower - (ic)->ic_curchanmaxpwr : 0)
+@@ -324,6 +327,9 @@
+ 	u_int16_t ic_newtxpowlimit; 		/* tx power limit to change to (in 0.5 dBm) */
+ 	u_int16_t ic_uapsdmaxtriggers; 		/* max triggers that could arrive */
+ 	u_int8_t ic_coverageclass; 		/* coverage class */
++	u_int8_t ic_protmode_rssi;			/* rssi threshold for protection mode */
++	u_int64_t ic_protmode_lasttrig;		/* last trigger for protection mode */
++	u_int16_t ic_protmode_timeout;		/* protection mode timeout */
+ 
+ 	/* Channel state:
+ 	 *
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2312,6 +2312,12 @@
+ 		    IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
+ 			retv = ENETRESET;
+ 		break;
++	case IEEE80211_PARAM_PROTMODE_TIMEOUT:
++		ic->ic_protmode_timeout = value;
++		break;
++	case IEEE80211_PARAM_PROTMODE_RSSI:
++		ic->ic_protmode_rssi = value;
++		break;
+ 	case IEEE80211_PARAM_MCASTCIPHER:
+ 		if ((vap->iv_caps & cipher2cap(value)) == 0 &&
+ 		    !ieee80211_crypto_available(vap, value))
+@@ -2955,6 +2961,12 @@
+ 	case IEEE80211_PARAM_PROTMODE:
+ 		param[0] = ic->ic_protmode;
+ 		break;
++	case IEEE80211_PARAM_PROTMODE_TIMEOUT:
++		param[0] = ic->ic_protmode_timeout;
++		break;
++	case IEEE80211_PARAM_PROTMODE_RSSI:
++		param[0] = ic->ic_protmode_rssi;
++		break;
+ 	case IEEE80211_PARAM_MCASTCIPHER:
+ 		param[0] = rsn->rsn_mcastcipher;
+ 		break;
+@@ -5346,6 +5358,14 @@
+ 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protmode" },
+ 	{ IEEE80211_PARAM_PROTMODE,
+ 	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protmode" },
++	{ IEEE80211_PARAM_PROTMODE_RSSI,
++	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protrssi" },
++	{ IEEE80211_PARAM_PROTMODE_RSSI,
++	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protrssi" },
++	{ IEEE80211_PARAM_PROTMODE_TIMEOUT,
++	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "prottime" },
++	{ IEEE80211_PARAM_PROTMODE_TIMEOUT,
++	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_prottime" },
+ 	{ IEEE80211_PARAM_MCASTCIPHER,
+ 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcastcipher" },
+ 	{ IEEE80211_PARAM_MCASTCIPHER,
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -1877,6 +1877,17 @@
+ 
+ 	ieee80211_scan_timeout(ic);
+ 	ieee80211_timeout_stations(&ic->ic_sta);
++	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
++		(ic->ic_protmode_lasttrig + ic->ic_protmode_timeout * HZ <
++			jiffies)) {
++		struct ieee80211vap *tmpvap;
++
++		/* expire protection mode */
++		ic->ic_flags &= ~IEEE80211_F_USEPROT;
++		TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++			tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++		}
++	}
+ 
+ 	ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ;
+ 	add_timer(&ic->ic_inact);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/347-tuning.patch kamikaze_7.09/package/madwifi/patches/347-tuning.patch
--- kamikaze_7.09.orig/package/madwifi/patches/347-tuning.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/347-tuning.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,99 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -10265,11 +10265,11 @@
+ 	sc->sc_currates = rt;
+ 	sc->sc_curmode = mode;
+ 	/*
+-	 * All protection frames are transmitted at 2Mb/s for
+-	 * 11g, otherwise at 1Mb/s.
++	 * All protection frames are transmitted at 11Mb/s for
++	 * 11g, otherwise at 2Mb/s.
+ 	 * XXX select protection rate index from rate table.
+ 	 */
+-	sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 1 : 0);
++	sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 3 : 1);
+ 	/* rate index used to send mgt frames */
+ 	sc->sc_minrateix = 0;
+ }
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -272,6 +272,10 @@
+ #define AES_ICV_FIELD_SIZE      8       /* AES ICV field size */
+ #define EXT_IV_FIELD_SIZE       4       /* ext IV field size */
+ 
++/* This is what the HAL uses by default for 11a+g */
++#define ATH_DEFAULT_CWMIN	15
++#define ATH_DEFAULT_CWMAX	1023
++
+ /* XR specific macros */
+ 
+ #define XR_DEFAULT_GRPPOLL_RATE_STR 	"0.25 1 1 3 3 6 6 20"
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -197,7 +197,7 @@
+ 		unsigned int x = 0, tt = 0;
+ 		unsigned int cix = rt->info[rix].controlRate;
+ 		int rts = 0, cts = 0;
+-		int cw = WIFI_CW_MIN;
++		int cw = ATH_DEFAULT_CWMIN;
+ 
+ 		KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+ 
+@@ -281,7 +281,7 @@
+ 		tt += (long_retries + 1) * ath_hal_computetxtime(sc->sc_ah, rt, length,
+ 							rix, AH_TRUE);
+ 		for (x = 0; x <= short_retries + long_retries; x++) {
+-			cw = MIN(WIFI_CW_MAX, (cw + 1) * 2);
++			cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
+ 			tt += (t_slot * cw / 2);
+ 		}
+ 		return tt;
+--- a/ath_rate/minstrel/minstrel.h
++++ b/ath_rate/minstrel/minstrel.h
+@@ -180,14 +180,6 @@
+ #define MAX(a,b)        ((a) > (b) ? (a) : (b))
+ #endif
+ 
+-#if 0
+-#define WIFI_CW_MIN 31
+-#define WIFI_CW_MAX 1023
+-#else
+-#define WIFI_CW_MIN 3
+-#define WIFI_CW_MAX 10
+-#endif
+-
+ /*
+  * Definitions for pulling the rate and trie counts from
+  * a 5212 h/w descriptor. These Don't belong here; the
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -170,7 +170,7 @@
+ 	struct ieee80211com *ic = &sc->sc_ic;
+ 	unsigned int tt = 0;
+ 	unsigned int x;
+-	unsigned int cw = WIFI_CW_MIN;
++	unsigned int cw = ATH_DEFAULT_CWMIN;
+ 	unsigned int cix = rt->info[rix].controlRate;
+ 	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+ 
+@@ -254,7 +254,7 @@
+ 	tt += (long_retries+1)*ath_hal_computetxtime(sc->sc_ah, rt, length,
+ 						rix, AH_TRUE);
+ 	for (x = 0; x <= short_retries + long_retries; x++) {
+-		cw = MIN(WIFI_CW_MAX, (cw + 1) * 2);
++		cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
+ 		tt += (t_slot * cw / 2);
+ 	}
+ 	return tt;
+--- a/ath_rate/sample/sample.h
++++ b/ath_rate/sample/sample.h
+@@ -106,9 +106,6 @@
+ #define MAX(a,b)        ((a) > (b) ? (a) : (b))
+ #endif
+ 
+-#define WIFI_CW_MIN 31
+-#define WIFI_CW_MAX 1023
+-
+ /*
+  * Definitions for pulling the rate and trie counts from
+  * a 5212 h/w descriptor. These Don't belong here; the
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/348-ackcts.patch kamikaze_7.09/package/madwifi/patches/348-ackcts.patch
--- kamikaze_7.09.orig/package/madwifi/patches/348-ackcts.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/348-ackcts.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,38 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -2721,6 +2721,9 @@
+ static int
+ ath_set_ack_bitrate(struct ath_softc *sc, int high)
+ {
++	if (!sc->sc_ackrate_override)
++		return 0;
++
+ 	if (ar_device(sc->devid) == 5212 || ar_device(sc->devid) == 5213) {
+ 		/* set ack to be sent at low bit-rate */
+ 		/* registers taken from the OpenBSD 5212 HAL */
+@@ -10780,8 +10783,13 @@
+ 				break;
+ #endif
+ 			case ATH_ACKRATE:
+-				sc->sc_ackrate = val;
+-				ath_set_ack_bitrate(sc, sc->sc_ackrate);
++				if (val == -1)
++					sc->sc_ackrate_override = 0;
++				else {
++					sc->sc_ackrate_override = 1;
++					sc->sc_ackrate = val;
++					ath_set_ack_bitrate(sc, sc->sc_ackrate);
++				}
+ 				break;
+ 			case ATH_RP:
+ 				ath_rp_record(sc,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -681,6 +681,7 @@
+ 	unsigned int	sc_devstopped:1;	/* stopped due to of no tx bufs */
+ 	unsigned int	sc_stagbeacons:1;	/* use staggered beacons */
+ 	unsigned int	sc_dfswait:1;		/* waiting on channel for radar detect */
++	unsigned int	sc_ackrate_override:1;	/* override ack rate */
+ 	unsigned int	sc_ackrate:1;		/* send acks at high bitrate */
+ 	unsigned int	sc_dfs_cac:1;		/* waiting on channel for radar detect */
+ 	unsigned int	sc_hasintmit:1;		/* Interference mitigation */
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/349-reset.patch kamikaze_7.09/package/madwifi/patches/349-reset.patch
--- kamikaze_7.09.orig/package/madwifi/patches/349-reset.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/349-reset.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,12 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8853,8 +8853,7 @@
+ 		 * needed to do the reset with chanchange = AH_FALSE in order
+ 		 * to receive traffic when peforming high velocity channel
+ 		 * changes. */
+-		if (!ath_hal_reset(ah, sc->sc_opmode, &hchan, AH_TRUE, &status)   ||
+-		    !ath_hal_reset(ah, sc->sc_opmode, &hchan, AH_FALSE, &status)) {
++		if (!ath_hal_reset(ah, sc->sc_opmode, &hchan, AH_TRUE, &status)) {
+ 			EPRINTF(sc, "Unable to reset channel %u (%u MHz) "
+ 				"flags 0x%x '%s' (HAL status %u)\n",
+ 				ieee80211_chan2ieee(ic, chan), chan->ic_freq,
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/350-wisoc_softled.patch kamikaze_7.09/package/madwifi/patches/350-wisoc_softled.patch
--- kamikaze_7.09.orig/package/madwifi/patches/350-wisoc_softled.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/350-wisoc_softled.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -245,6 +245,8 @@
+ 	num_activesc++;
+ 	/* Ready to process interrupts */
+ 
++	sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
++	sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
+ 	sc->aps_sc.sc_invalid = 0;
+ 	return 0;
+ 
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/351-scanlist.patch kamikaze_7.09/package/madwifi/patches/351-scanlist.patch
--- kamikaze_7.09.orig/package/madwifi/patches/351-scanlist.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/351-scanlist.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,875 @@
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -317,147 +317,6 @@
+ #undef ISPROBE
+ }
+ 
+-static struct ieee80211_channel *
+-find11gchannel(struct ieee80211com *ic, int i, int freq)
+-{
+-	struct ieee80211_channel *c;
+-	int j;
+-
+-	/*
+-	 * The normal ordering in the channel list is b channel
+-	 * immediately followed by g so optimize the search for
+-	 * this.  We'll still do a full search just in case.
+-	 */
+-	for (j = i+1; j < ic->ic_nchans; j++) {
+-		c = &ic->ic_channels[j];
+-		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+-			return c;
+-	}
+-	for (j = 0; j < i; j++) {
+-		c = &ic->ic_channels[j];
+-		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+-			return c;
+-	}
+-	return NULL;
+-}
+-static const u_int chanflags[] = {
+-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_AUTO */
+-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
+-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
+-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
+-	IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
+-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
+-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_TURBO_G */
+-	IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */
+-};
+-
+-static void
+-add_channels(struct ieee80211com *ic,
+-	struct ieee80211_scan_state *ss,
+-	enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
+-{
+-	struct ieee80211_channel *c, *cg;
+-	u_int modeflags;
+-	int i;
+-
+-	KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+-	modeflags = chanflags[mode];
+-	for (i = 0; i < nfreq; i++) {
+-		c = ieee80211_find_channel(ic, freq[i], modeflags);
+-		if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
+-			continue;
+-		if (mode == IEEE80211_MODE_AUTO) {
+-			/*
+-			 * XXX special-case 11b/g channels so we select
+-			 *     the g channel if both are present.
+-			 */
+-			if (IEEE80211_IS_CHAN_B(c) &&
+-			    (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
+-				c = cg;
+-		}
+-		if (ss->ss_last >= IEEE80211_SCAN_MAX)
+-			break;
+-		ss->ss_chans[ss->ss_last++] = c;
+-	}
+-}
+-
+-static const u_int16_t rcl1[] =		/* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */
+-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
+-static const u_int16_t rcl2[] =		/* 4 MKK channels: 34, 38, 42, 46 */
+-{ 5170, 5190, 5210, 5230 };
+-static const u_int16_t rcl3[] =		/* 2.4Ghz ch: 1,6,11,7,13 */
+-{ 2412, 2437, 2462, 2442, 2472 };
+-static const u_int16_t rcl4[] =		/* 5 FCC channel: 149, 153, 161, 165 */
+-{ 5745, 5765, 5785, 5805, 5825 };
+-static const u_int16_t rcl7[] =		/* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */
+-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
+-static const u_int16_t rcl8[] =		/* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
+-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
+-static const u_int16_t rcl9[] =		/* 2.4Ghz ch: 14 */
+-{ 2484 };
+-static const u_int16_t rcl10[] =	/* Added Korean channels 2312-2372 */
+-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
+-static const u_int16_t rcl11[] =	/* Added Japan channels in 4.9/5.0 spectrum */
+-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
+-#ifdef ATH_TURBO_SCAN
+-static const u_int16_t rcl5[] =		/* 3 static turbo channels */
+-{ 5210, 5250, 5290 };
+-static const u_int16_t rcl6[] =		/* 2 static turbo channels */
+-{ 5760, 5800 };
+-static const u_int16_t rcl6x[] =		/* 4 FCC3 turbo channels */
+-{ 5540, 5580, 5620, 5660 };
+-static const u_int16_t rcl12[] =		/* 2.4Ghz Turbo channel 6 */
+-{ 2437 };
+-static const u_int16_t rcl13[] =		/* dynamic Turbo channels */
+-{ 5200, 5240, 5280, 5765, 5805 };
+-#endif /* ATH_TURBO_SCAN */
+-
+-struct scanlist {
+-	u_int16_t	mode;
+-	u_int16_t	count;
+-	const u_int16_t	*list;
+-};
+-
+-#define	IEEE80211_MODE_TURBO_STATIC_A	IEEE80211_MODE_MAX
+-#define	X(a)	.count = sizeof(a)/sizeof(a[0]), .list = a
+-
+-static const struct scanlist staScanTable[] = {
+-	{ IEEE80211_MODE_11B,   		X(rcl3) },
+-	{ IEEE80211_MODE_11A,   		X(rcl1) },
+-	{ IEEE80211_MODE_11A,   		X(rcl2) },
+-	{ IEEE80211_MODE_11B,   		X(rcl8) },
+-	{ IEEE80211_MODE_11B,   		X(rcl9) },
+-	{ IEEE80211_MODE_11A,   		X(rcl4) },
+-#ifdef ATH_TURBO_SCAN
+-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl5) },
+-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl6) },
+-	{ IEEE80211_MODE_TURBO_A,		X(rcl6x) },
+-	{ IEEE80211_MODE_TURBO_A,		X(rcl13) },
+-#endif /* ATH_TURBO_SCAN */
+-	{ IEEE80211_MODE_11A,			X(rcl7) },
+-	{ IEEE80211_MODE_11B,			X(rcl10) },
+-	{ IEEE80211_MODE_11A,			X(rcl11) },
+-#ifdef ATH_TURBO_SCAN
+-	{ IEEE80211_MODE_TURBO_G,		X(rcl12) },
+-#endif /* ATH_TURBO_SCAN */
+-	{ .list = NULL }
+-};
+-
+-#undef X
+-
+-static int
+-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
+-{
+-	int i;
+-
+-	for (; scan->list != NULL; scan++) {
+-		for (i = 0; i < scan->count; i++)
+-			if (scan->list[i] == c->ic_freq)
+-				return 1;
+-	}
+-	return 0;
+-}
+-
+ /*
+  * Start a station-mode scan by populating the channel list.
+  */
+@@ -466,81 +325,14 @@
+ {
+ 	struct ieee80211com *ic = vap->iv_ic;
+ 	struct sta_table *st = ss->ss_priv;
+-	const struct scanlist *scan;
+ 	enum ieee80211_phymode mode;
+ 	struct ieee80211_channel *c;
+ 	int i;
+ 
+ 	ss->ss_last = 0;
+-	/*
+-	 * Use the table of ordered channels to construct the list
+-	 * of channels for scanning.  Any channels in the ordered
+-	 * list not in the master list will be discarded.
+-	 */
+-	for (scan = staScanTable; scan->list != NULL; scan++) {
+-		mode = scan->mode;
+-		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
+-			/*
+-			 * If a desired mode was specified, scan only 
+-			 * channels that satisfy that constraint.
+-			 */
+-			if (vap->iv_des_mode != mode) {
+-				/*
+-				 * The scan table marks 2.4Ghz channels as b
+-				 * so if the desired mode is 11g, then use
+-				 * the 11b channel list but upgrade the mode.
+-				 */
+-				if (vap->iv_des_mode != IEEE80211_MODE_11G ||
+-				    mode != IEEE80211_MODE_11B)
+-					continue;
+-				mode = IEEE80211_MODE_11G;	/* upgrade */
+-			}
+-		} else {
+-			/*
+-			 * This lets ieee80211_scan_add_channels
+-			 * upgrade an 11b channel to 11g if available.
+-			 */
+-			if (mode == IEEE80211_MODE_11B)
+-				mode = IEEE80211_MODE_AUTO;
+-		}
+-		/* XR does not operate on turbo channels */
+-		if ((vap->iv_flags & IEEE80211_F_XR) &&
+-		    (mode == IEEE80211_MODE_TURBO_A ||
+-		     mode == IEEE80211_MODE_TURBO_G))
+-			continue;
+-		/*
+-		 * Add the list of the channels; any that are not
+-		 * in the master channel list will be discarded.
+-		 */
+-		add_channels(ic, ss, mode, scan->list, scan->count);
+-	}
+-
+-	/*
+-	 * Add the channels from the ic (from HAL) that are not present
+-	 * in the staScanTable.
+-	 */
+-	for (i = 0; i < ic->ic_nchans; i++) {
+-		c = &ic->ic_channels[i];
+-		/*
+-		 * scan dynamic turbo channels in normal mode.
+-		 */
+-		if (IEEE80211_IS_CHAN_DTURBO(c))
+-			continue;
+-		mode = ieee80211_chan2mode(c);
+-		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
+-			/*
+-			 * If a desired mode was specified, scan only 
+-			 * channels that satisfy that constraint.
+-			 */
+-			if (vap->iv_des_mode != mode)
+-				continue;
+-
+-		}
+-		if (!checktable(staScanTable, c))
+-			ss->ss_chans[ss->ss_last++] = c;
+-	}
+-
++	ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
+ 	ss->ss_next = 0;
++
+ 	/* XXX tunables */
+ 	/* 
+ 	 * The scanner will stay on station for ss_maxdwell ms (using a 
+@@ -749,17 +541,7 @@
+ 	fail = 0;
+ 	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan)))
+ 		fail |= 0x01;
+-	/*
+-	 * NB: normally the desired mode is used to construct
+-	 * the channel list, but it's possible for the scan
+-	 * cache to include entries for stations outside this
+-	 * list so we check the desired mode here to weed them
+-	 * out.
+-	 */
+-	if (vap->iv_des_mode != IEEE80211_MODE_AUTO &&
+-	    (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
+-	    chanflags[vap->iv_des_mode])
+-		fail |= 0x01;
++
+ 	if (vap->iv_opmode == IEEE80211_M_IBSS) {
+ 		if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
+ 			fail |= 0x02;
+@@ -1168,78 +950,6 @@
+ 	.scan_default		= ieee80211_sta_join,
+ };
+ 
+-/*
+- * Start an adhoc-mode scan by populating the channel list.
+- */
+-static int
+-adhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
+-{
+-	struct ieee80211com *ic = vap->iv_ic;
+-	struct sta_table *st = ss->ss_priv;
+-	const struct scanlist *scan;
+-	enum ieee80211_phymode mode;
+-
+-	ss->ss_last = 0;
+-	/*
+-	 * Use the table of ordered channels to construct the list
+-	 * of channels for scanning.  Any channels in the ordered
+-	 * list not in the master list will be discarded.
+-	 */
+-	for (scan = staScanTable; scan->list != NULL; scan++) {
+-		mode = scan->mode;
+-		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
+-			/*
+-			 * If a desired mode was specified, scan only 
+-			 * channels that satisfy that constraint.
+-			 */
+-			if (vap->iv_des_mode != mode) {
+-				/*
+-				 * The scan table marks 2.4Ghz channels as b
+-				 * so if the desired mode is 11g, then use
+-				 * the 11b channel list but upgrade the mode.
+-				 */
+-				if (vap->iv_des_mode != IEEE80211_MODE_11G ||
+-				    mode != IEEE80211_MODE_11B)
+-					continue;
+-				mode = IEEE80211_MODE_11G;	/* upgrade */
+-			}
+-		} else {
+-			/*
+-			 * This lets ieee80211_scan_add_channels
+-			 * upgrade an 11b channel to 11g if available.
+-			 */
+-			if (mode == IEEE80211_MODE_11B)
+-				mode = IEEE80211_MODE_AUTO;
+-		}
+-		/* XR does not operate on turbo channels */
+-		if ((vap->iv_flags & IEEE80211_F_XR) &&
+-		    (mode == IEEE80211_MODE_TURBO_A ||
+-		     mode == IEEE80211_MODE_TURBO_G))
+-			continue;
+-		/*
+-		 * Add the list of the channels; any that are not
+-		 * in the master channel list will be discarded.
+-		 */
+-		add_channels(ic, ss, mode, scan->list, scan->count);
+-	}
+-	ss->ss_next = 0;
+-	/* XXX tunables */
+-	ss->ss_mindwell = msecs_to_jiffies(200);	/* 200ms */
+-	ss->ss_maxdwell = msecs_to_jiffies(200);	/* 200ms */
+-
+-#ifdef IEEE80211_DEBUG
+-	if (ieee80211_msg_scan(vap)) {
+-		printk("%s: scan set ", vap->iv_dev->name);
+-		ieee80211_scan_dump_channels(ss);
+-		printk(" dwell min %ld max %ld\n",
+-			ss->ss_mindwell, ss->ss_maxdwell);
+-	}
+-#endif /* IEEE80211_DEBUG */
+-
+-	st->st_newscan = 1;
+-
+-	return 0;
+-}
+ 
+ /*
+  * Select a channel to start an adhoc network on.
+@@ -1405,7 +1115,7 @@
+ 	.scan_name		= "default",
+ 	.scan_attach		= sta_attach,
+ 	.scan_detach		= sta_detach,
+-	.scan_start		= adhoc_start,
++	.scan_start		= sta_start,
+ 	.scan_restart		= sta_restart,
+ 	.scan_cancel		= sta_cancel,
+ 	.scan_end		= adhoc_pick_bss,
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -278,6 +278,11 @@
+ 			("channel with bogus ieee number %u", c->ic_ieee));
+ 		setbit(ic->ic_chan_avail, c->ic_ieee);
+ 
++		if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)
++			c->ic_scanflags |= IEEE80211_NOSCAN_SET;
++		else
++			c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
++
+ 		/* Identify mode capabilities. */
+ 		if (IEEE80211_IS_CHAN_A(c))
+ 			ic->ic_modecaps |= 1 << IEEE80211_MODE_11A;
+--- a/net80211/_ieee80211.h
++++ b/net80211/_ieee80211.h
+@@ -132,6 +132,11 @@
+ 	IEEE80211_SCAN_FIRST	= 2,	/* take first suitable candidate */
+ };
+ 
++enum ieee80211_scanflags {
++	IEEE80211_NOSCAN_DEFAULT = (1 << 0),
++	IEEE80211_NOSCAN_SET     = (1 << 1),
++};
++
+ /*
+  * Channels are specified by frequency and attributes.
+  */
+@@ -142,6 +147,7 @@
+ 	int8_t ic_maxregpower;	/* maximum regulatory tx power in dBm */
+ 	int8_t ic_maxpower;	/* maximum tx power in dBm */
+ 	int8_t ic_minpower;	/* minimum tx power in dBm */
++	u_int8_t ic_scanflags;
+ };
+ 
+ #define	IEEE80211_CHAN_MAX	255
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -555,6 +555,7 @@
+ #define	IEEE80211_IOCTL_WDSADDMAC	(SIOCIWFIRSTPRIV+26)
+ #define	IEEE80211_IOCTL_WDSDELMAC	(SIOCIWFIRSTPRIV+28)
+ #define	IEEE80211_IOCTL_KICKMAC		(SIOCIWFIRSTPRIV+30)
++#define	IEEE80211_IOCTL_SETSCANLIST	(SIOCIWFIRSTPRIV+31)
+ 
+ enum {
+ 	IEEE80211_WMMPARAMS_CWMIN       = 1,
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -129,131 +129,7 @@
+ 
+ static int ap_flush(struct ieee80211_scan_state *);
+ static void action_tasklet(IEEE80211_TQUEUE_ARG);
+-static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, 
+-		int i, int freq);
+ 
+-static const u_int chanflags[] = {
+-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_AUTO */
+-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
+-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
+-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
+-	IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
+-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_TURBO_A */ /* for turbo mode 
+-							      * look for AP in 
+-							      * normal channel 
+-							      */
+-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_TURBO_G */
+-	IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */
+-};
+-
+-static const u_int16_t rcl1[] =		/* 8 FCC channel: 52, 56, 60, 64, 
+-					 *                36, 40, 44, 48 */
+-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
+-static const u_int16_t rcl2[] =		/* 4 MKK channels: 34, 38, 42, 46 */
+-{ 5170, 5190, 5210, 5230 };
+-static const u_int16_t rcl3[] =		/* 2.4Ghz ch: 1,6,11,7,13 */
+-{ 2412, 2437, 2462, 2442, 2472 };
+-static const u_int16_t rcl4[] =		/* 5 FCC channel: 149, 153, 161, 165 */
+-{ 5745, 5765, 5785, 5805, 5825 };
+-static const u_int16_t rcl7[] =		/* 11 ETSI channel: 100, 104, 108, 112,
+-					 *                  116, 120, 124, 128, 
+-					 *                  132, 136, 140 */
+-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
+-static const u_int16_t rcl8[] =		/* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
+-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
+-static const u_int16_t rcl9[] =		/* 2.4Ghz ch: 14 */
+-{ 2484 };
+-static const u_int16_t rcl10[] =	/* Added Korean channels 2312-2372 */
+-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
+-static const u_int16_t rcl11[] =	/* Added Japan channels in 4.9/5.0 spectrum */
+-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
+-#ifdef ATH_TURBO_SCAN
+-static const u_int16_t rcl5[] =		/* 3 static turbo channels */
+-{ 5210, 5250, 5290 };
+-static const u_int16_t rcl6[] =		/* 2 static turbo channels */
+-{ 5760, 5800 };
+-static const u_int16_t rcl6x[] =		/* 4 FCC3 turbo channels */
+-{ 5540, 5580, 5620, 5660 };
+-static const u_int16_t rcl12[] =		/* 2.4Ghz Turbo channel 6 */
+-{ 2437 };
+-static const u_int16_t rcl13[] =		/* dynamic Turbo channels */
+-{ 5200, 5240, 5280, 5765, 5805 };
+-#endif /* ATH_TURBO_SCAN */
+-
+-struct scanlist {
+-	u_int16_t	mode;
+-	u_int16_t	count;
+-	const u_int16_t	*list;
+-};
+-
+-#define	IEEE80211_MODE_TURBO_STATIC_A	IEEE80211_MODE_MAX
+-#define	X(a)	.count = ARRAY_SIZE(a), .list = a
+-
+-static const struct scanlist staScanTable[] = {
+-	{ IEEE80211_MODE_11B,   		X(rcl3)  },
+-	{ IEEE80211_MODE_11A,   		X(rcl1)  },
+-	{ IEEE80211_MODE_11A,   		X(rcl2)  },
+-	{ IEEE80211_MODE_11B,   		X(rcl8)  },
+-	{ IEEE80211_MODE_11B,   		X(rcl9)  },
+-	{ IEEE80211_MODE_11A,   		X(rcl4)  },
+-#ifdef ATH_TURBO_SCAN
+-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl5)  },
+-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl6)  },
+-	{ IEEE80211_MODE_TURBO_A,		X(rcl6x) },
+-	{ IEEE80211_MODE_TURBO_A,		X(rcl13) },
+-#endif /* ATH_TURBO_SCAN */
+-	{ IEEE80211_MODE_11A,			X(rcl7)  },
+-	{ IEEE80211_MODE_11B,			X(rcl10) },
+-	{ IEEE80211_MODE_11A,			X(rcl11) },
+-#ifdef ATH_TURBO_SCAN
+-	{ IEEE80211_MODE_TURBO_G,		X(rcl12) },
+-#endif /* ATH_TURBO_SCAN */
+-	{ .list = NULL }
+-};
+-
+-#undef X
+-/* This function must be invoked with locks acquired */
+-static void
+-add_channels(struct ieee80211com *ic,
+-	struct ieee80211_scan_state *ss,
+-	enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
+-{
+-	struct ieee80211_channel *c, *cg;
+-	u_int modeflags;
+-	int i;
+-
+-	KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+-	modeflags = chanflags[mode];
+-	for (i = 0; i < nfreq; i++) {
+-		c = ieee80211_find_channel(ic, freq[i], modeflags);
+-		if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
+-			continue;
+-		if (mode == IEEE80211_MODE_AUTO) {
+-			/* XXX special-case 11b/g channels so we select
+-			 *     the g channel if both are present. */
+-			if (IEEE80211_IS_CHAN_B(c) &&
+-			    (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
+-				c = cg;
+-		}
+-		if (ss->ss_last >= IEEE80211_SCAN_MAX)
+-			break;
+-		ss->ss_chans[ss->ss_last++] = c;
+-	}
+-}
+-
+-/* This function must be invoked with locks acquired */
+-static int
+-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
+-{
+-	int i;
+-
+-	for (; scan->list != NULL; scan++) {
+-		for (i = 0; i < scan->count; i++)
+-			if (scan->list[i] == c->ic_freq)
+-				return 1;
+-	}
+-	return 0;
+-}
+ 
+ /*
+  * Attach prior to any scanning work.
+@@ -327,29 +203,6 @@
+ 		ieee80211_saveie(iep, ie);
+ }
+ 
+-/* This function must be invoked with locks acquired */
+-static struct ieee80211_channel *
+-find11gchannel(struct ieee80211com *ic, int i, int freq)
+-{
+-	struct ieee80211_channel *c;
+-	int j;
+-
+-	/* The normal ordering in the channel list is b channel
+-	 * immediately followed by g so optimize the search for
+-	 * this.  We'll still do a full search just in case. */
+-	for (j = i + 1; j < ic->ic_nchans; j++) {
+-		c = &ic->ic_channels[j];
+-		if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
+-			return c;
+-	}
+-	for (j = 0; j < i; j++) {
+-		c = &ic->ic_channels[j];
+-		if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
+-			return c;
+-	}
+-	return NULL;
+-}
+-
+ /*
+  * Start an ap scan by populating the channel list.
+  */
+@@ -358,8 +211,6 @@
+ {
+ 	struct ap_state *as 	    = ss->ss_priv;
+ 	struct ieee80211com *ic     = NULL;
+-	const struct scanlist *sl   = NULL;
+-	struct ieee80211_channel *c = NULL;
+ 	int i;
+ 	unsigned int mode = 0;
+ 
+@@ -368,80 +219,8 @@
+ 	/* Determine mode flags to match, or leave zero for auto mode */
+ 	as->as_vap_desired_mode = vap->iv_des_mode;
+ 	as->as_required_mode    = 0;
+-	if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) {
+-		as->as_required_mode = chanflags[as->as_vap_desired_mode];
+-		if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && 
+-		    (as->as_required_mode != IEEE80211_CHAN_ST)) {
+-			/* Fixup for dynamic turbo flags */
+-			if (as->as_vap_desired_mode == IEEE80211_MODE_11G)
+-				as->as_required_mode = IEEE80211_CHAN_108G;
+-			else
+-				as->as_required_mode = IEEE80211_CHAN_108A;
+-		}
+-	}
+-
+-	ss->ss_last = 0;
+-	/* Use the table of ordered channels to construct the list
+-	 * of channels for scanning.  Any channels in the ordered
+-	 * list not in the master list will be discarded. */
+-	for (sl = staScanTable; sl->list != NULL; sl++) {
+-		mode = sl->mode;
+-
+-		/* The scan table marks 2.4Ghz channels as b
+-		 * so if the desired mode is 11g, then use
+-		 * the 11b channel list but upgrade the mode. */
+-		if (as->as_vap_desired_mode &&
+-		    (as->as_vap_desired_mode != mode) && 
+-		    (as->as_vap_desired_mode == IEEE80211_MODE_11G) && 
+-		    (mode == IEEE80211_MODE_11B))
+-			mode = IEEE80211_MODE_11G;
+-
+-		/* If we are in "AUTO" mode, upgrade the mode to auto. 
+-		 * This lets add_channels upgrade an 11b channel to 
+-		 * 11g if available. */
+-		if (!as->as_vap_desired_mode && (mode == IEEE80211_MODE_11B))
+-			mode = IEEE80211_MODE_AUTO;
+-
+-		/* Add the list of the channels; any that are not
+-		 * in the master channel list will be discarded. */
+-		add_channels(ic, ss, mode, sl->list, sl->count);
+-	}
+-
+-	/* Add the channels from the ic (from HAL) that are not present
+-	 * in the staScanTable, assuming they pass the sanity checks... */
+-	for (i = 0; i < ic->ic_nchans; i++) {
+-		c = &ic->ic_channels[i];
+-
+-		/* XR is not supported on turbo channels */
+-		if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR)
+-			continue;
++	ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
+ 
+-		/* Dynamic channels are scanned in base mode */
+-		if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c))
+-			continue;
+-
+-		/* Use any 11g channel instead of 11b one. */
+-		if (vap->iv_des_mode == IEEE80211_MODE_AUTO && 
+-		    IEEE80211_IS_CHAN_B(c) &&
+-		    find11gchannel(ic, i, c->ic_freq))
+-			continue;
+-
+-		/* Do not add channels already put into the scan list by the
+-		 * scan table - these have already been filtered by mode
+-		 * and for whether they are in the active channel list. */
+-		if (checktable(staScanTable, c))
+-			continue;
+-
+-		/* Make sure the channel is active */
+-		if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
+-			continue;
+-
+-		/* Don't overrun */
+-		if (ss->ss_last >= IEEE80211_SCAN_MAX)
+-			break;
+-
+-		ss->ss_chans[ss->ss_last++] = c;
+-	}
+ 	ss->ss_next = 0;
+ 	/* XXX tunables */
+ 	ss->ss_mindwell = msecs_to_jiffies(200);	/* 200ms */
+@@ -759,13 +538,6 @@
+ 		if (IEEE80211_IS_CHAN_RADAR(c->chan))
+ 			continue;
+ 
+-		/* Do not select 802.11a ST if mode is specified and is not 
+-		 * 802.11a ST */
+-		if (as->as_required_mode &&
+-		    IEEE80211_IS_CHAN_STURBO(c->chan) &&
+-		    (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A))
+-			continue;
+-
+ 		/* Verify mode matches any fixed mode specified */
+ 		if((c->chan->ic_flags & as->as_required_mode) != 
+ 				as->as_required_mode)
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -958,6 +958,80 @@
+ 	}
+ }
+ 
++static const u_int chanflags[] = {
++	0,	/* IEEE80211_MODE_AUTO */
++	IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
++	IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
++	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
++	IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
++	IEEE80211_CHAN_A,	/* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
++	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_TURBO_G */
++	IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */
++};
++
++static struct ieee80211_channel *
++find11gchannel(struct ieee80211com *ic, int i, int freq)
++{
++	struct ieee80211_channel *c;
++	int j;
++
++	/*
++	 * The normal ordering in the channel list is b channel
++	 * immediately followed by g so optimize the search for
++	 * this.  We'll still do a full search just in case.
++	 */
++	for (j = i+1; j < ic->ic_nchans; j++) {
++		c = &ic->ic_channels[j];
++		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
++			return c;
++	}
++	for (j = 0; j < i; j++) {
++		c = &ic->ic_channels[j];
++		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
++			return c;
++	}
++	return NULL;
++}
++
++
++void
++ieee80211_scan_add_channels(struct ieee80211com *ic,
++	struct ieee80211_scan_state *ss,
++	enum ieee80211_phymode mode)
++{
++	struct ieee80211_channel *c, *cg;
++	u_int modeflags;
++	int i;
++
++	KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
++	modeflags = chanflags[mode];
++	for (i = 0; i < ic->ic_nchans; i++) {
++		c = &ic->ic_channels[i];
++		if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
++			continue;
++		if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
++			continue;
++		if (modeflags &&
++			((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
++			 (modeflags & IEEE80211_CHAN_ALLTURBO)))
++			continue;
++		if (mode == IEEE80211_MODE_AUTO) {
++			/*
++			 * XXX special-case 11b/g channels so we select
++			 *     the g channel if both are present.
++			 */
++			if (IEEE80211_IS_CHAN_B(c) &&
++			    (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
++				continue;
++		}
++		if (ss->ss_last >= IEEE80211_SCAN_MAX)
++			break;
++		ss->ss_chans[ss->ss_last++] = c;
++	}
++}
++EXPORT_SYMBOL(ieee80211_scan_add_channels);
++
++
+ /*
+  * Execute radar channel change. This is called when a radar/dfs
+  * signal is detected.  AP mode only.  Return 1 on success, 0 on
+--- a/net80211/ieee80211_scan.h
++++ b/net80211/ieee80211_scan.h
+@@ -219,4 +219,7 @@
+ void ieee80211_scanner_unregister(enum ieee80211_opmode,
+ 	const struct ieee80211_scanner *);
+ void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
++void ieee80211_scan_add_channels(struct ieee80211com *ic,
++	struct ieee80211_scan_state *ss,
++	enum ieee80211_phymode mode);
+ #endif /* _NET80211_IEEE80211_SCAN_H_ */
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -3873,6 +3873,106 @@
+ 	return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
+ }
+ 
++static inline void setflag(struct ieee80211_channel *c, int flag)
++{
++	if (flag)
++		c->ic_scanflags |= IEEE80211_NOSCAN_SET;
++	else
++		c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
++}
++
++static void setscanflag(struct ieee80211com *ic, int min, int max, int set)
++{
++	int i;
++
++	for (i = 0; i < ic->ic_nchans; i++) {
++		struct ieee80211_channel *c = &ic->ic_channels[i];
++
++		if (min == -1) {
++			if (!(c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT))
++				setflag(c, set);
++		} else if ((c->ic_freq >= min) && (c->ic_freq <= max)) {
++			setflag(c, set);
++		}
++	}
++}
++
++static int
++ieee80211_ioctl_setscanlist(struct net_device *dev,
++	struct iw_request_info *info,
++	struct iw_point *data, char *extra)
++{
++	struct ieee80211vap *vap = dev->priv;
++	struct ieee80211com *ic = vap->iv_ic;
++	char *s, *next;
++	int val = 1;
++
++	if (data->length <= 0)
++		return -EINVAL;
++
++	s = kmalloc(data->length + 1, GFP_KERNEL);
++	if (!s)
++		return -ENOMEM;
++
++	memset(s, 0, data->length + 1);
++	if (copy_from_user(s, data->pointer, data->length))
++		return -EFAULT;
++
++	s[data->length - 1] = '\0';		/* ensure null termination */
++
++	switch(*s) {
++		case '-':
++			val = 1;
++			break;
++		case '+':
++			val = 0;
++			break;
++		default:
++			goto error;
++	}
++	s++;
++	next = s;
++	do {
++		next = strchr(s, ',');
++		if (next) {
++			*next = 0;
++			next++;
++		}
++		if (!strcmp(s, "ALL")) {
++			setscanflag(ic, 0, 10000, val);
++		} else if (!strcmp(s, "REG")) {
++			setscanflag(ic, -1, -1, val);
++		} else {
++			int min, max;
++			char *n, *end = NULL;
++
++			n = strchr(s, '-');
++			if (n) {
++				*n = 0;
++				n++;
++			}
++			min = simple_strtoul(s, &end, 10);
++			if (end && *end)
++				goto error;
++			if (n) {
++				max = simple_strtoul(n, &end, 10);
++				if (end && *end)
++					goto error;
++			} else {
++				max = min;
++			}
++			setscanflag(ic, min, max, val);
++		}
++		s = next;
++	} while (next);
++	return 0;
++
++error:
++	if (s)
++		kfree(s);
++	return -EINVAL;
++}
++
+ static int
+ ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
+ 	void *w, char *extra)
+@@ -5656,6 +5756,8 @@
+ 	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
+ 	{IEEE80211_PARAM_MINRATE,
+ 	 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
++	{ IEEE80211_IOCTL_SETSCANLIST,
++	 IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
+ 
+ #ifdef ATH_REVERSE_ENGINEERING
+ 	/*
+@@ -5753,6 +5855,7 @@
+ 	set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
+ 	set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac),
+ 	set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac),
++	set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist),
+ #ifdef ATH_REVERSE_ENGINEERING
+ 	set_priv(IEEE80211_IOCTL_READREG, ieee80211_ioctl_readreg),
+ 	set_priv(IEEE80211_IOCTL_WRITEREG, ieee80211_ioctl_writereg),
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/352-ani_fix.patch kamikaze_7.09/package/madwifi/patches/352-ani_fix.patch
--- kamikaze_7.09.orig/package/madwifi/patches/352-ani_fix.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/352-ani_fix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,288 @@
+Index: madwifi-trunk-r3314/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3314.orig/ath/if_ath.c	2008-06-13 10:39:28.000000000 +0200
++++ madwifi-trunk-r3314/ath/if_ath.c	2008-06-13 10:39:54.000000000 +0200
+@@ -1014,9 +1014,7 @@
+ 	 */
+ 	sc->sc_hasveol = ath_hal_hasveol(ah);
+ 
+-	/* Interference mitigation/ambient noise immunity (ANI).
+-	 * In modes other than HAL_M_STA, it causes receive sensitivity
+-	 * problems for OFDM. */
++	/* Interference mitigation/ambient noise immunity (ANI). */
+ 	sc->sc_hasintmit = ath_hal_hasintmit(ah);
+ 
+ 	/* get mac address from hardware */
+@@ -1144,6 +1142,11 @@
+ 	sc->sc_rp_lasttsf	= 0;
+ 	sc->sc_last_tsf		= 0;
+ 
++	/* set all 3 to auto */
++	sc->sc_intmit = -1;
++	sc->sc_noise_immunity = -1;
++	sc->sc_ofdm_weak_det = -1;
++
+ 	return 0;
+ bad3:
+ 	ieee80211_ifdetach(ic);
+@@ -2347,16 +2350,6 @@
+ 		}
+ 		if (status & HAL_INT_MIB) {
+ 			sc->sc_stats.ast_mib++;
+-			/* When the card receives lots of PHY errors, the MIB
+-			 * interrupt will fire at a very rapid rate. We will use
+-			 * a timer to enforce at least 1 jiffy delay between
+-			 * MIB interrupts. This should be unproblematic, since
+-			 * the hardware will continue to update the counters in 
+-			 * the mean time. */
+-			sc->sc_imask &= ~HAL_INT_MIB;
+-			ath_hal_intrset(ah, sc->sc_imask);
+-			mod_timer(&sc->sc_mib_enable, jiffies + 1);
+-
+ 			/* Let the HAL handle the event. */
+ 			ath_hal_mibevent(ah, &sc->sc_halstats);
+ 		}
+@@ -2426,6 +2419,43 @@
+ 	return flags;
+ }
+ 
++static int ath_setintmit(struct ath_softc *sc)
++{
++	struct ath_hal *ah = sc->sc_ah;
++	int ret;
++	int val;
++
++	if (!sc->sc_hasintmit)
++		return 0;
++
++	switch(sc->sc_intmit) {
++		case -1:
++			if (sc->sc_opmode != IEEE80211_M_MONITOR)
++				val = 1;
++			else
++				val = 0;
++			break;
++		case 0: /* disabled */
++		case 1: /* enabled */
++			val = sc->sc_intmit;
++			break;
++		default:
++			return 0;
++	}
++	ret = ath_hal_setintmit(ah, val);
++	if (val)
++		goto done;
++
++	/* manual settings */
++	if ((sc->sc_noise_immunity >= 0) && (sc->sc_noise_immunity <= 5))
++		ath_hal_setcapability(ah, HAL_CAP_INTMIT, 2, sc->sc_noise_immunity, NULL);
++	if ((sc->sc_ofdm_weak_det == 0) || (sc->sc_ofdm_weak_det == 1))
++		ath_hal_setcapability(ah, HAL_CAP_INTMIT, 3, sc->sc_ofdm_weak_det, NULL);
++
++done:
++	return ret;
++}
++
+ /*
+  * Context: process context
+  */
+@@ -2491,8 +2521,7 @@
+ 	if (sc->sc_softled)
+ 		ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
+ 
+-	if ((sc->sc_opmode != HAL_M_STA) && sc->sc_hasintmit)
+-		ath_hal_setintmit(ah, 0);
++	ath_setintmit(sc);
+ 
+ 	/*
+ 	 * This is needed only to setup initial state
+@@ -2528,7 +2557,7 @@
+ 	 * Enable MIB interrupts when there are hardware phy counters.
+ 	 * Note we only do this (at the moment) for station mode.
+ 	 */
+-	if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)
++	if (sc->sc_needmib && ath_hal_getintmit(ah, NULL))
+ 		sc->sc_imask |= HAL_INT_MIB;
+ 	ath_hal_intrset(ah, sc->sc_imask);
+ 
+@@ -2785,9 +2814,7 @@
+ 		EPRINTF(sc, "Unable to reset hardware: '%s' (HAL status %u)\n",
+ 			ath_get_hal_status_desc(status), status);
+ 
+-	if ((sc->sc_opmode != HAL_M_STA) && sc->sc_hasintmit)
+-		ath_hal_setintmit(ah, 0);
+-
++	ath_setintmit(sc);
+ 	ath_update_txpow(sc);		/* update tx power state */
+ 	ath_radar_update(sc);
+ 	ath_setdefantenna(sc, sc->sc_defant);
+@@ -4165,6 +4192,8 @@
+ 	if (sc->sc_nmonvaps > 0)
+ 		rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
+ 			  HAL_RX_FILTER_PROBEREQ | HAL_RX_FILTER_PROM);
++	if (sc->sc_hasintmit && !sc->sc_needmib && ath_hal_getintmit(ah, NULL))
++		rfilt |= HAL_RX_FILTER_PHYERR;
+ 	if (sc->sc_curchan.privFlags & CHANNEL_DFS)
+ 		rfilt |= (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR);
+ 	return rfilt;
+@@ -6513,9 +6542,6 @@
+ 			rs->rs_rssi = 0;
+ 
+ 		len = rs->rs_datalen;
+-		/* DMA sync. dies spectacularly if len == 0 */
+-		if (len == 0)
+-			goto rx_next;
+ 
+ 		if (rs->rs_more) {
+ 			/*
+@@ -8865,9 +8891,7 @@
+ 		if (sc->sc_softled)
+ 			ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
+ 
+-		if ((sc->sc_opmode != HAL_M_STA) && sc->sc_hasintmit)
+-			ath_hal_setintmit(ah, 0);
+-
++		ath_setintmit(sc);
+ 		sc->sc_curchan = hchan;
+ 		ath_update_txpow(sc);		/* update tx power state */
+ 		ath_radar_update(sc);
+@@ -10644,9 +10668,54 @@
+ 	ATH_RP_IGNORED 		= 24,
+ 	ATH_RADAR_IGNORED       = 25,
+ 	ATH_MAXVAPS  		= 26,
++	ATH_INTMIT			= 27,
++	ATH_NOISE_IMMUNITY	= 28,
++	ATH_OFDM_WEAK_DET	= 29
+ };
+ 
+ static int
++ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val)
++{
++	int ret;
++
++	switch(ctl) {
++	case ATH_INTMIT:
++		sc->sc_intmit = val;
++		break;
++	case ATH_NOISE_IMMUNITY:
++		sc->sc_noise_immunity = val;
++		break;
++	case ATH_OFDM_WEAK_DET:
++		sc->sc_ofdm_weak_det = val;
++		break;
++	default:
++		return -EINVAL;
++	}
++	ret = ath_setintmit(sc);
++	ath_calcrxfilter(sc);
++	return ret;
++}
++
++static int
++ath_sysctl_get_intmit(struct ath_softc *sc, long ctl, u_int *val)
++{
++	struct ath_hal *ah = sc->sc_ah;
++
++	switch(ctl) {
++	case ATH_INTMIT:
++		*val = (ath_hal_getcapability(ah, HAL_CAP_INTMIT, 1, NULL) == HAL_OK);
++		break;
++	case ATH_NOISE_IMMUNITY:
++		return ath_hal_getcapability(ah, HAL_CAP_INTMIT, 2, val);
++	case ATH_OFDM_WEAK_DET:
++		return ath_hal_getcapability(ah, HAL_CAP_INTMIT, 3, val);
++	default:
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static int
+ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
+ {
+ 	struct ath_softc *sc = ctl->extra1;
+@@ -10832,6 +10901,11 @@
+ 			case ATH_RADAR_IGNORED:
+ 				sc->sc_radar_ignored = val;
+ 				break;
++			case ATH_INTMIT:
++			case ATH_NOISE_IMMUNITY:
++			case ATH_OFDM_WEAK_DET:
++				ret = ath_sysctl_set_intmit(sc, (long)ctl->extra2, val);
++				break;
+ 			default:
+ 				ret = -EINVAL;
+ 				break;
+@@ -10898,6 +10972,11 @@
+ 		case ATH_RADAR_IGNORED:
+ 			val = sc->sc_radar_ignored;
+ 			break;
++		case ATH_INTMIT:
++		case ATH_NOISE_IMMUNITY:
++		case ATH_OFDM_WEAK_DET:
++			ret = ath_sysctl_get_intmit(sc, (long)ctl->extra2, &val);
++			break;
+ 		default:
+ 			ret = -EINVAL;
+ 			break;
+@@ -11075,6 +11154,24 @@
+ 	  .proc_handler = ath_sysctl_halparam,
+ 	  .extra2	= (void *)ATH_RADAR_IGNORED,
+ 	},
++	{ .ctl_name	= CTL_AUTO,
++	  .procname     = "intmit",
++	  .mode         = 0644,
++	  .proc_handler = ath_sysctl_halparam,
++	  .extra2	= (void *)ATH_INTMIT,
++	},
++	{ .ctl_name	= CTL_AUTO,
++	  .procname     = "noise_immunity",
++	  .mode         = 0644,
++	  .proc_handler = ath_sysctl_halparam,
++	  .extra2	= (void *)ATH_NOISE_IMMUNITY,
++	},
++	{ .ctl_name	= CTL_AUTO,
++	  .procname     = "ofdm_weak_det",
++	  .mode         = 0644,
++	  .proc_handler = ath_sysctl_halparam,
++	  .extra2	= (void *)ATH_OFDM_WEAK_DET,
++	},
+ 	{ 0 }
+ };
+ 
+Index: madwifi-trunk-r3314/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3314.orig/ath/if_athvar.h	2008-06-13 10:39:28.000000000 +0200
++++ madwifi-trunk-r3314/ath/if_athvar.h	2008-06-13 10:39:32.000000000 +0200
+@@ -693,6 +693,10 @@
+ 	unsigned int sc_txcont_power; /* Continuous transmit power in 0.5dBm units */
+ 	unsigned int sc_txcont_rate;  /* Continuous transmit rate in Mbps */
+ 
++	int8_t sc_intmit; /* Interference mitigation enabled, -1 = auto, based on mode, 0/1 = off/on */
++	int8_t sc_noise_immunity; /* Noise immunity level, 0-4, -1 == auto) */
++	int8_t sc_ofdm_weak_det; /* OFDM weak frames detection, -1 == auto */
++
+ 	/* rate tables */
+ 	const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX];
+ 	const HAL_RATE_TABLE *sc_currates;	/* current rate table */
+Index: madwifi-trunk-r3314/ath/if_ath_hal.h
+===================================================================
+--- madwifi-trunk-r3314.orig/ath/if_ath_hal.h	2008-06-13 10:39:26.000000000 +0200
++++ madwifi-trunk-r3314/ath/if_ath_hal.h	2008-06-13 10:39:32.000000000 +0200
+@@ -67,14 +67,14 @@
+ 
+ static inline HAL_BOOL ath_hal_getdiagstate(struct ath_hal *ah, int request,
+ 					    const void *args, u_int32_t argsize,
+-					    void **result,
++					    void *result,
+ 					    u_int32_t *resultsize)
+ {
+ 	HAL_BOOL ret;
+ 	ATH_HAL_LOCK_IRQ(ah->ah_sc);
+ 	ath_hal_set_function(__func__);
+ 	ret =
+-	    ah->ah_getDiagState(ah, request, args, argsize, *result,
++	    ah->ah_getDiagState(ah, request, args, argsize, result,
+ 				resultsize);
+ 	ath_hal_set_function(NULL);
+ 	ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/400-changeset_r3402.patch kamikaze_7.09/package/madwifi/patches/400-changeset_r3402.patch
--- kamikaze_7.09.orig/package/madwifi/patches/400-changeset_r3402.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/400-changeset_r3402.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,35 @@
+--- a/ath_hal/ah_os.h
++++ b/ath_hal/ah_os.h
+@@ -194,10 +194,6 @@
+  */
+ #if (AH_BYTE_ORDER == AH_BIG_ENDIAN)
+ #define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000))
+-#else
+-#define is_reg_le(__reg) 1
+-#endif
+-
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
+ #define _OS_REG_WRITE(_ah, _reg, _val) do {			\
+ 	 is_reg_le(_reg) ?					\
+@@ -219,6 +215,21 @@
+ 	 readl((_ah)->ah_sh + (_reg)) :				\
+ 	 cpu_to_le32(readl((_ah)->ah_sh + (_reg))))
+ #endif				/* KERNEL_VERSION(2,6,12) */
++#else				/* AH_BYTE_ORDER != AH_BIG_ENDIAN */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
++#define _OS_REG_WRITE(_ah, _reg, _val) do {			\
++	 iowrite32((_val), (_ah)->ah_sh + (_reg));		\
++	} while (0)
++#define _OS_REG_READ(_ah, _reg)					\
++	ioread32((_ah)->ah_sh + (_reg))
++#else
++#define _OS_REG_WRITE(_ah, _reg, _val) do {			\
++	 writel((_val), (_ah)->ah_sh + (_reg));			\
++	} while (0)
++#define _OS_REG_READ(_ah, _reg)					\
++	readl((_ah)->ah_sh + (_reg))
++#endif				/* KERNEL_VERSION(2,6,12) */
++#endif				/* AH_BYTE_ORDER != AH_BIG_ENDIAN */
+ 
+ /*
+  * The functions in this section are not intended to be invoked by MadWifi
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/401-changeset_r3602.patch kamikaze_7.09/package/madwifi/patches/401-changeset_r3602.patch
--- kamikaze_7.09.orig/package/madwifi/patches/401-changeset_r3602.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/401-changeset_r3602.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -312,6 +312,8 @@
+ /* __skb_append got a third parameter in 2.6.14 */
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+ #define __skb_append(a,b,c)	__skb_append(a, b)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
++#define __skb_append(a,b,c)	__skb_queue_after(c, a, b)
+ #endif
+ 
+ /*
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/402-changeset_r3603.patch kamikaze_7.09/package/madwifi/patches/402-changeset_r3603.patch
--- kamikaze_7.09.orig/package/madwifi/patches/402-changeset_r3603.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/402-changeset_r3603.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,176 @@
+--- a/Makefile
++++ b/Makefile
+@@ -40,10 +40,7 @@
+ # Makefile for the HAL-based Atheros driver.
+ #
+ 
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)
+ 
+ ifneq (svnversion.h,$(MAKECMDGOALS))
+--- a/ath/Makefile
++++ b/ath/Makefile
+@@ -40,10 +40,7 @@
+ # Makefile for the Atheros WLAN driver.
+ #
+ 
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+ 
+ ifeq ($(strip $(BUS)),AHB)
+--- a/ath_hal/Makefile
++++ b/ath_hal/Makefile
+@@ -40,10 +40,7 @@
+ # Makefile for the Atheros WLAN driver.
+ #
+ 
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+ 
+ include $(TOP)/Makefile.inc
+--- a/ath_rate/Makefile
++++ b/ath_rate/Makefile
+@@ -1,7 +1,4 @@
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+ 
+ obj-y := amrr/ onoe/ sample/ minstrel/
+--- a/ath_rate/amrr/Makefile
++++ b/ath_rate/amrr/Makefile
+@@ -40,10 +40,7 @@
+ #
+ # Makefile for the Atheros Rate Control Support.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m		+= ath_rate_amrr.o
+--- a/ath_rate/minstrel/Makefile
++++ b/ath_rate/minstrel/Makefile
+@@ -38,10 +38,7 @@
+ #
+ # Makefile for the Atheros Rate Control Support.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m		+= ath_rate_minstrel.o
+--- a/ath_rate/onoe/Makefile
++++ b/ath_rate/onoe/Makefile
+@@ -40,10 +40,7 @@
+ #
+ # Makefile for the Atheros Rate Control Support.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m		+= ath_rate_onoe.o
+--- a/ath_rate/sample/Makefile
++++ b/ath_rate/sample/Makefile
+@@ -38,10 +38,7 @@
+ #
+ # Makefile for the Atheros Rate Control Support.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m		+= ath_rate_sample.o
+--- a/net80211/Makefile
++++ b/net80211/Makefile
+@@ -39,10 +39,7 @@
+ #
+ # Makefile for the 802.11 WLAN modules.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+ #
+ # There is one authenticator mechanism: an in-kernel implementation
+--- a/regression/Makefile
++++ b/regression/Makefile
+@@ -1,7 +1,4 @@
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+ 
+ obj-y := ccmp/ tkip/ wep/
+--- a/regression/ccmp/Makefile
++++ b/regression/ccmp/Makefile
+@@ -1,10 +1,7 @@
+ #
+ # Makefile for the CCMP regression test.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m			+= ath_test_ccmp.o
+--- a/regression/tkip/Makefile
++++ b/regression/tkip/Makefile
+@@ -1,10 +1,7 @@
+ #
+ # Makefile for the TKIP regression test.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m			+= ath_test_tkip.o
+--- a/regression/wep/Makefile
++++ b/regression/wep/Makefile
+@@ -1,10 +1,7 @@
+ #
+ # Makefile for the WEP regression test.
+ #
+-ifeq ($(obj),)
+-obj=	.
+-endif
+-
++obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/../..
+ 
+ obj-m			+= ath_test_wep.o
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/403-changeset_r3605.patch kamikaze_7.09/package/madwifi/patches/403-changeset_r3605.patch
--- kamikaze_7.09.orig/package/madwifi/patches/403-changeset_r3605.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/403-changeset_r3605.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,70 @@
+--- a/include/compat.h
++++ b/include/compat.h
+@@ -182,6 +182,13 @@
+ #define DEV_ATH CTL_UNNUMBERED
+ #endif
+ 
++/* __skb_append got a third parameter in 2.6.14 */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
++#define __skb_queue_after(_list, _old, _new)	__skb_append(_old, _new)
++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
++#define __skb_queue_after(_list, _old, _new)	__skb_append(_old, _new, _list)
++#endif
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* _ATH_COMPAT_H_ */
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -309,13 +309,6 @@
+ #define	ACL_LOCK_CHECK(_as)
+ #endif
+ 
+-/* __skb_append got a third parameter in 2.6.14 */
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+-#define __skb_append(a,b,c)	__skb_append(a, b)
+-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
+-#define __skb_append(a,b,c)	__skb_queue_after(c, a, b)
+-#endif
+-
+ /*
+  * Per-node power-save queue definitions.  Beware of control
+  * flow with IEEE80211_NODE_SAVEQ_LOCK/IEEE80211_NODE_SAVEQ_UNLOCK.
+@@ -359,16 +352,16 @@
+ 	_skb = __skb_dequeue(&(_ni)->ni_savedq);		\
+ 	(_qlen) = skb_queue_len(&(_ni)->ni_savedq);		\
+ } while (0)
+-#define	_IEEE80211_NODE_SAVEQ_ENQUEUE(_ni, _skb, _qlen, _age) do {\
+-	struct sk_buff *tail = skb_peek_tail(&(_ni)->ni_savedq);\
+-	if (tail != NULL) {					\
+-		_age -= M_AGE_GET(tail);			\
+-		__skb_append(tail, _skb, &(_ni)->ni_savedq);	\
+-	} else { 						\
+-		__skb_queue_head(&(_ni)->ni_savedq, _skb);	\
+-	}							\
+-	M_AGE_SET(_skb, _age);					\
+-	(_qlen) = skb_queue_len(&(_ni)->ni_savedq); 		\
++#define	_IEEE80211_NODE_SAVEQ_ENQUEUE(_ni, _skb, _qlen, _age) do {	\
++	struct sk_buff *tail = skb_peek_tail(&(_ni)->ni_savedq);	\
++	if (tail != NULL) {						\
++		_age -= M_AGE_GET(tail);				\
++		__skb_queue_after(&(_ni)->ni_savedq, tail, _skb);	\
++	} else { 							\
++		__skb_queue_head(&(_ni)->ni_savedq, _skb);		\
++	}								\
++	M_AGE_SET(_skb, _age);						\
++	(_qlen) = skb_queue_len(&(_ni)->ni_savedq); 			\
+ } while (0)
+ 
+ /*
+--- a/net80211/ieee80211_power.c
++++ b/net80211/ieee80211_power.c
+@@ -243,7 +243,7 @@
+ 	tail = skb_peek_tail(&ni->ni_savedq);
+ 	if (tail != NULL) {
+ 		age -= M_AGE_GET(tail);
+-		__skb_append(tail, skb, &ni->ni_savedq);
++		__skb_queue_after(&ni->ni_savedq, tail, skb);
+ 	} else
+ 		__skb_queue_head(&ni->ni_savedq, skb);
+ 	M_AGE_SET(skb, age);
diff -Nur kamikaze_7.09.orig/package/madwifi/patches/404-linux24_fix.patch kamikaze_7.09/package/madwifi/patches/404-linux24_fix.patch
--- kamikaze_7.09.orig/package/madwifi/patches/404-linux24_fix.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/madwifi/patches/404-linux24_fix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,17 @@
+Index: madwifi-trunk-r3314/ath_hal/Makefile
+===================================================================
+--- madwifi-trunk-r3314.orig/ath_hal/Makefile	2008-06-07 17:08:42.354855646 +0200
++++ madwifi-trunk-r3314/ath_hal/Makefile	2008-06-07 17:09:03.260046968 +0200
+@@ -78,10 +78,11 @@
+ quiet_cmd_uudecode = UUDECODE $@
+       cmd_uudecode = $(obj)/uudecode -o $@ $<
+ 
+-$(obj)/$(TARGET).hal.o: $(HAL)/public/$(TARGET).hal.o.uu $(obj)/uudecode
+ ifdef LINUX24
++$(TARGET).hal.o: $(HAL)/public/$(TARGET).hal.o.uu $(obj)/uudecode
+ 	$(Q)$(obj)/uudecode -o $@ $<
+ else
++$(obj)/$(TARGET).hal.o: $(HAL)/public/$(TARGET).hal.o.uu $(obj)/uudecode
+ 	$(call if_changed,uudecode)
+ endif
+ 
diff -Nur kamikaze_7.09.orig/package/netperf/files/netserver.init kamikaze_7.09/package/netperf/files/netserver.init
--- kamikaze_7.09.orig/package/netperf/files/netserver.init	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/netperf/files/netserver.init	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+START=50
+
+start() {
+	/usr/bin/netserver
+}
+
+stop() {
+	killall netserver
+}
diff -Nur kamikaze_7.09.orig/package/netperf/Makefile kamikaze_7.09/package/netperf/Makefile
--- kamikaze_7.09.orig/package/netperf/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/netperf/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 8398 2007-08-11 16:06:22Z olli $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=netperf
+PKG_VERSION:=2.4.3
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.netperf.org/netperf/
+PKG_MD5SUM:=8b1f48500443b18b825ae2763a51eced
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/netperf
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=Network performance measurement tool
+  URL:=http://www.netperf.org/
+endef
+
+define Package/netperf/install
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/netserver.init $(1)/etc/init.d/netserver
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/netperf $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/netserver $(1)/usr/bin/
+	$(INSTALL_DIR) $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/arr_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/packet_byte_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/sctp_stream_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/snapshot_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/tcp_range_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/tcp_rr_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/tcp_stream_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/udp_rr_script $(1)/lib/netperf
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/udp_stream_script $(1)/lib/netperf
+endef
+
+$(eval $(call BuildPackage,netperf))
diff -Nur kamikaze_7.09.orig/package/olsrd/files/olsr.config kamikaze_7.09/package/olsrd/files/olsr.config
--- kamikaze_7.09.orig/package/olsrd/files/olsr.config	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/files/olsr.config	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,40 @@
+config "olsr" "general"
+	option DebugLevel	'0'
+	option IpVersion	'4'
+	option AllowNoInt	'yes'
+	option Pollrate	'0.025'
+	option TcRedundancy	'2'
+	option MprCoverage	'7'
+	option LinkQualityFishEye	'1'
+	option LinkQualityWinSize	'100'
+	option LinkQualityDijkstraLimit	'0 9.0'
+	option LinkQualityLevel	'2'
+	option UseHysteresis	'no'
+
+config "LoadPlugin" "arprefresh"
+	option Library	'olsrd_arprefresh.so.0.1'
+
+config "LoadPlugin" "dyn_gw_plain"
+	option Library	'olsrd_dyn_gw_plain.so.0.4'
+
+config "LoadPlugin" "nameservice"
+	option Library	'olsrd_nameservice.so.0.3'
+	option name	'sven-ola-gs'
+	option hosts_file	'/var/etc/hosts'
+	option suffix	'.olsr'
+	option latlon_infile	'/var/run/latlon.txt'
+
+config "LoadPlugin" "txtinfo"
+	option Library	'olsrd_txtinfo.so.0.1'
+	option Accept	'127.0.0.1'
+
+config "Interface"
+	option Interface	"wlan"
+	option HelloInterval	'6.0'
+	option HelloValidityTime	'108.0'
+	option TcInterval	'4.0'
+	option TcValidityTime	'324.0'
+	option MidInterval	'18.0'
+	option MidValidityTime	'324.0'
+	option HnaInterval	'18.0'
+	option HnaValidityTime	'108.0'
diff -Nur kamikaze_7.09.orig/package/olsrd/files/olsrd.init kamikaze_7.09/package/olsrd/files/olsrd.init
--- kamikaze_7.09.orig/package/olsrd/files/olsrd.init	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/files/olsrd.init	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,333 @@
+#!/bin/sh /etc/rc.common
+START=50
+
+BIN=olsrd
+CONF_F=/var/etc/olsrd.conf
+USE_CONF_F=
+DEFAULT=/etc/default/olsrd
+RUN_D=/var/run
+PID_F=$RUN_D/$BIN.pid
+
+format_olsr_option() {
+	local str="$*"
+	echo -n "$str" | tr -d '\n\r\t\v '
+}
+
+format_olsr_value() {
+	local str="$*"
+	echo -n "$str" | tr -d '\n\r\v'
+}
+
+format_olsr_param() {
+	local str="$*"
+	echo -n "$str" | tr -d '\n\r\v"'
+}
+
+format_uci_varname() {
+	local str="$*"
+	echo -n "$str" | sed -e 's/[^a-zA-Z0-9_]//g'
+}
+
+foreach_olsr() {
+	local cfg="$1"
+	local option
+	local value
+
+	for option in $CONFIG_OPTIONS
+	do
+		config_get value "$cfg" "$option"
+		option=$(format_olsr_option "$option")
+		value=$(format_olsr_value "$value")
+
+		if [ -n "$value" -a "$option" != "ConfigFile" ]; then
+			echo "$option $value" >> "$CONF_F"
+		fi
+	done
+	echo >> "$CONF_F"
+}
+
+foreach_Hna4() {
+	local cfg="$1"
+	local netaddr
+	local netmask
+
+	config_get netaddr "$cfg" NetAddr
+	config_get netmask "$cfg" NetMask
+	netaddr=$(format_olsr_option "$netaddr")
+	netmask=$(format_olsr_option "$netmask")
+
+	if [ -n "$netaddr" -a -n "$netmask" ]; then
+		if [ "$HNA4_COUNT" -le 0 ]; then
+			echo "Hna4" >> "$CONF_F"
+			echo "{" >> "$CONF_F"
+		fi
+
+		echo "	$netaddr $netmask" >> "$CONF_F"
+		HNA4_COUNT=$((HNA4_COUNT + 1))
+	fi
+}
+
+write_Hna4() {
+	if [ "$HNA4_COUNT" -gt 0 ]; then
+		echo "}" >> "$CONF_F"
+		echo >> "$CONF_F"
+	fi
+}
+
+foreach_Hna6() {
+	local cfg="$1"
+	local netaddr
+	local netmask
+
+	config_get netaddr "$cfg" NetAddr
+	config_get prefix "$cfg" Prefix
+	netaddr=$(format_olsr_option "$netaddr")
+	prefix=$(format_olsr_option "$prefix")
+
+	if [ -n "$netaddr" -a -n "$prefix" ]; then
+		if [ "$HNA6_COUNT" -le 0 ]; then
+			echo "Hna6" >> "$CONF_F"
+			echo "{" >> "$CONF_F"
+		fi
+
+		echo "	$netaddr $prefix" >> "$CONF_F"
+		HNA6_COUNT=$((HNA6_COUNT + 1))
+	fi
+}
+
+write_Hna6() {
+	if [ "$HNA6_COUNT" -gt 0 ]; then
+		echo "}" >> "$CONF_F"
+		echo >> "$CONF_F"
+	fi
+}
+
+foreach_IpcConnect() {
+	local cfg="$1"
+	local option
+	local value
+	local c
+
+	echo "IpcConnect" >> "$CONF_F"
+	echo -n "{" >> "$CONF_F"
+
+	for option in $CONFIG_OPTIONS
+	do
+		config_get value "$cfg" "$option"
+		option=$(format_olsr_option "$option")
+		value=$(format_olsr_value "$value")
+
+		if [ -n "$value" ]; then
+			if [ "$option" = "Host" ]; then
+				for item in $value
+				do
+					echo >> "$CONF_F"
+					echo -n "	$option $item" >> "$CONF_F"
+				done
+			elif [ "$option" = "Net" ]; then
+				c=0
+				for item in $value
+				do
+					if [ $((c % 2)) -eq 0 ]; then
+						echo >> "$CONF_F"
+						echo -n "	$option $item" >> "$CONF_F"
+					else
+						echo -n " $item" >> "$CONF_F"
+					fi
+					c=$((c + 1))
+				done
+			else
+				echo >> "$CONF_F"
+				echo -n "	$option $value" >> "$CONF_F"
+			fi
+		fi
+	done
+
+	echo >> "$CONF_F"
+	echo "}" >> "$CONF_F"
+	echo >> "$CONF_F"
+}
+
+foreach_LoadPlugin() {
+	local cfg="$1"
+	local library
+	local option
+	local value
+	local is_ip_addr
+	local item
+	local c
+
+	config_get library "$cfg" Library
+	library=$(format_olsr_param "$library")
+
+	if [ -n "$library" ]; then
+		echo "LoadPlugin \"$library\"" >> "$CONF_F"
+		echo -n "{" >> "$CONF_F"
+
+		for option in $CONFIG_OPTIONS
+		do
+			config_get value "$cfg" "$option"
+			option=$(format_olsr_param "$option")
+			value=$(format_olsr_param "$value")
+
+			if [ -n "$value" ]; then
+				option=$(echo "$option" | sed -e y/[_]/[-]/)
+
+				is_ip_addr=$(echo "$option" | sed -e 's/[^-]//g')
+				if [ "$is_ip_addr" = "---" ]; then
+					option=$(echo "$option" | sed -e y/[-]/[.]/)
+				fi
+
+				if [ "$option" = "Ping" -o "$option" = "redistribute" -o "$option" = "Host" -o "$option" = "NonOlsrIf" -o "$option" = "name" -o "$is_ip_addr" = "---" ]; then
+					for item in $value
+					do
+						echo >> "$CONF_F"
+						echo -n "	PlParam \"$option\" \"$item\"" >> "$CONF_F"
+					done
+				elif [ "$option" = "Net" -o "$option" = "HNA" ]; then
+					c=0
+					for item in $value
+					do
+						if [ $((c % 2)) -eq 0 ]; then
+							echo >> "$CONF_F"
+							echo -n "	PlParam \"$option\" \"$item" >> "$CONF_F"
+						else
+							echo -n " $item\"" >> "$CONF_F"
+						fi
+						c=$((c + 1))
+					done
+				elif [ "$option" != "Library" ]; then
+					echo >> "$CONF_F"
+					echo -n "	PlParam \"$option\" \"$value\"" >> "$CONF_F"
+				fi
+			fi
+		done
+
+		echo >> "$CONF_F"
+		echo "}" >> "$CONF_F"
+		echo >> "$CONF_F"
+	fi
+}
+
+foreach_Interface() {
+	local cfg="$1"
+	local interfaces
+	local interface
+	local ifname
+	local option
+	local value
+	local item
+	local c
+
+	config_get interfaces "$cfg" Interface
+
+	if [ -n "$interfaces" ]; then
+		echo -n "Interface" >> "$CONF_F"
+
+		for interface in $interfaces
+		do
+			interface=$(format_uci_varname "$interface")
+			config_get ifnames "$interface" ifname
+			for ifname in $ifnames
+			do
+				ifname=$(format_olsr_param "$ifname")
+				echo -n " \"$ifname\"" >> "$CONF_F"
+			done
+		done
+
+		echo >> "$CONF_F"
+		echo -n "{" >> "$CONF_F"
+
+		for option in $CONFIG_OPTIONS
+		do
+			config_get value "$cfg" "$option"
+			option=$(format_olsr_option "$option")
+			value=$(format_olsr_value "$value")
+
+			if [ -n "$value" ]; then
+				if [ "$option" = "LinkQualityMult" ]; then
+					c=0
+					for item in $value
+					do
+						if [ $((c % 2)) -eq 0 ]; then
+							echo >> "$CONF_F"
+							echo -n "	$option $item" >> "$CONF_F"
+						else
+							echo -n " $item" >> "$CONF_F"
+						fi
+						c=$((c + 1))
+					done
+				elif [ "$option" != "Interface" ]; then
+					echo >> "$CONF_F"
+					echo -n "	$option $value" >> "$CONF_F"
+				fi
+			fi
+		done
+
+		echo >> "$CONF_F"
+		echo "}" >> "$CONF_F"
+	fi
+}
+
+write_config() {
+	include /lib/network
+	scan_interfaces
+	config_load /var/state/network
+
+	config_cb() {
+		local cfgtype="$1"
+		local name="$2"
+		CONFIG_TYPE="$cfgtype"
+	}
+
+	option_cb() {
+		local varname="$1"
+		local value="$2"
+
+		if [ "$CONFIG_TYPE" = "OLSR" -a "$varname" = "ConfigFile" ]; then
+			USE_CONF_F="$value"
+		fi
+
+		if ! echo "$CONFIG_OPTIONS" | grep " $varname " > /dev/null; then
+			CONFIG_OPTIONS="$CONFIG_OPTIONS $varname "
+		fi
+	}
+
+	CONFIG_OPTIONS=""
+	config_load olsr
+
+	if [ -n "$USE_CONF_F" ]; then
+		return 0
+	else
+		USE_CONF_F="$CONF_F"
+	fi
+
+	mkdir -p $(dirname "$CONF_F")
+	> "$CONF_F"
+	config_foreach foreach_olsr olsr
+	HNA4_COUNT=0
+	config_foreach foreach_Hna4 Hna4
+	write_Hna4
+	HNA6_COUNT=0
+	config_foreach foreach_Hna6 Hna6
+	write_Hna6
+	config_foreach foreach_IpcConnect IpcConnect
+	config_foreach foreach_LoadPlugin LoadPlugin
+	config_foreach foreach_Interface Interface
+}
+
+start() {
+	[ -z "$USE_CONF_F" ] && write_config
+
+	[ -f $DEFAULT ] && . $DEFAULT
+	$BIN -f "$USE_CONF_F" -nofork $OPTIONS &
+
+	# write pid file (but strip out own pid ($$))
+	mkdir -p $RUN_D
+	PID=`pidof $BIN`
+	echo ${PID%$$} > $PID_F
+}
+
+stop() {
+	killall olsrd
+}
diff -Nur kamikaze_7.09.orig/package/olsrd/files/olsrd_secure_key kamikaze_7.09/package/olsrd/files/olsrd_secure_key
--- kamikaze_7.09.orig/package/olsrd/files/olsrd_secure_key	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/files/olsrd_secure_key	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1 @@
+1234567890123456
\ Kein Zeilenumbruch am Dateiende.
diff -Nur kamikaze_7.09.orig/package/olsrd/Makefile kamikaze_7.09/package/olsrd/Makefile
--- kamikaze_7.09.orig/package/olsrd/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,163 @@
+# 
+# Copyright (C) 2007 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 11266 2008-05-25 16:30:46Z blogic $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=olsrd
+PKG_VERSION:=0.5.6-rc5
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.olsr.org/releases/0.5
+PKG_MD5SUM:=139f71b37bd9a19804d0accf3a07b457
+
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/olsrd/template
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=OLSR (Optimized Link State Routing) daemon
+  URL:=http://www.olsr.org/
+  MENU:=1
+endef
+
+define Package/olsrd
+  $(call Package/olsrd/template)
+  MENU:=1
+endef
+
+define Package/olsrd/conffiles
+/etc/olsrd.conf
+endef
+
+define Package/olsrd-mod-dot-draw
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd
+  TITLE:=Dot topology information plugin
+endef
+
+define Package/olsrd-mod-bmf
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd +libpthread +kmod-tun
+  TITLE:=Basic multicast forwarding plugin
+endef
+
+define Package/olsrd-mod-dyn-gw
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd +libpthread
+  TITLE:=Dynamic internet gateway plugin
+endef
+
+define Package/olsrd-mod-httpinfo
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd
+  TITLE:=Small informative web server plugin
+endef
+
+define Package/olsrd-mod-nameservice
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd
+  TITLE:=Lightweight hostname resolver plugin
+endef
+
+define Package/olsrd-mod-secure
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd
+  TITLE:=Message signing plugin to secure routing domain
+endef
+
+define Package/olsrd-mod-txtinfo
+  $(call Package/olsrd/template)
+  DEPENDS:=olsrd
+  TITLE:=Small informative web server plugin
+endef
+
+define Package/olsrd-mod-secure/conffiles
+/etc/olsrd.d/olsrd_secure_key
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	rm -rf $(PKG_INSTALL_DIR)
+	mkdir -p $(PKG_INSTALL_DIR)
+	$(MAKE) -C "$(PKG_BUILD_DIR)" \
+		$(TARGET_CONFIGURE_OPTS) \
+		NODEBUG=1 \
+		CFLAGS="$(TARGET_CFLAGS)" \
+		OS="linux" \
+		INSTALL_PREFIX="$(PKG_INSTALL_DIR)" \
+		LIBDIR="$(PKG_INSTALL_DIR)/usr/lib" \
+		SBINDIR="$(PKG_INSTALL_DIR)/usr/sbin/" \
+		ETCDIR="$(PKG_INSTALL_DIR)/etc" \
+		MANDIR="$(PKG_INSTALL_DIR)/usr/share/man" \
+		STRIP="true" \
+		INSTALL_LIB="true" \
+		SUBDIRS="bmf dot_draw dyn_gw httpinfo nameservice secure txtinfo" \
+		all libs install install_libs
+endef
+
+define Package/olsrd/install
+	$(INSTALL_DIR) $(1)/etc/config
+	$(INSTALL_DATA) ./files/olsr.config $(1)/etc/config/olsr
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/src/cfgparser/olsrd.conf.example $(1)/etc/olsrd.conf
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/olsrd $(1)/usr/sbin/
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/olsrd.init $(1)/etc/init.d/olsrd
+endef
+
+define Package/olsrd-mod-dot-draw/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/dot_draw/olsrd_dot_draw.so.* $(1)/usr/lib/
+endef
+
+define Package/olsrd-mod-bmf/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/bmf/olsrd_bmf.so.* $(1)/usr/lib/
+endef
+
+define Package/olsrd-mod-dyn-gw/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/dyn_gw/olsrd_dyn_gw.so.* $(1)/usr/lib/
+endef
+
+define Package/olsrd-mod-httpinfo/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/httpinfo/olsrd_httpinfo.so.* $(1)/usr/lib/
+endef
+
+define Package/olsrd-mod-nameservice/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/nameservice/olsrd_nameservice.so.* $(1)/usr/lib/
+endef
+
+define Package/olsrd-mod-secure/install
+	$(INSTALL_DIR) $(1)/etc/olsrd.d
+	$(CP) ./files/olsrd_secure_key $(1)/etc/olsrd.d/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/secure/olsrd_secure.so.* $(1)/usr/lib/
+endef
+
+define Package/olsrd-mod-txtinfo/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/txtinfo/olsrd_txtinfo.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,olsrd))
+$(eval $(call BuildPackage,olsrd-mod-dot-draw))
+$(eval $(call BuildPackage,olsrd-mod-bmf))
+$(eval $(call BuildPackage,olsrd-mod-dyn-gw))
+$(eval $(call BuildPackage,olsrd-mod-httpinfo))
+$(eval $(call BuildPackage,olsrd-mod-nameservice))
+$(eval $(call BuildPackage,olsrd-mod-secure))
+$(eval $(call BuildPackage,olsrd-mod-txtinfo))
diff -Nur kamikaze_7.09.orig/package/olsrd/patches/100-debug_level.patch kamikaze_7.09/package/olsrd/patches/100-debug_level.patch
--- kamikaze_7.09.orig/package/olsrd/patches/100-debug_level.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/patches/100-debug_level.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,11 @@
+--- olsrd-0.4.10/files/olsrd.conf.default.rfc	2005-06-04 17:34:05.000000000 +0200
++++ olsrd-0.4.10.new/files/olsrd.conf.default.rfc	2006-05-21 21:44:55.000000000 +0200
+@@ -9,7 +9,7 @@
+ # Debug level(0-9)
+ # If set to 0 the daemon runs in the background
+ 
+-DebugLevel	1
++DebugLevel	0
+ 
+ # IP version to use (4 or 6)
+ 
diff -Nur kamikaze_7.09.orig/package/olsrd/patches/110-build_fix.patch kamikaze_7.09/package/olsrd/patches/110-build_fix.patch
--- kamikaze_7.09.orig/package/olsrd/patches/110-build_fix.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/patches/110-build_fix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,13 @@
+Index: olsrd-0.5.4/Makefile
+===================================================================
+--- olsrd-0.5.4.orig/Makefile	2007-11-03 11:33:37.075400513 +0100
++++ olsrd-0.5.4/Makefile	2007-11-03 11:33:47.171975883 +0100
+@@ -71,8 +71,6 @@
+ $(CFGOBJS):
+ 		$(MAKECMD) -C $(CFGDIR)
+ 
+-# generate it always
+-.PHONY: src/builddata.c
+ src/builddata.c:
+ 	@$(RM) "$@"
+ 	@echo "#include \"defs.h\"" >> "$@" 
diff -Nur kamikaze_7.09.orig/package/olsrd/patches/120-dyn_gw_interval.patch kamikaze_7.09/package/olsrd/patches/120-dyn_gw_interval.patch
--- kamikaze_7.09.orig/package/olsrd/patches/120-dyn_gw_interval.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/olsrd/patches/120-dyn_gw_interval.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,20 @@
+--- olsrd-0.5.4/lib/dyn_gw/src/olsrd_dyn_gw-orig.c      2007-10-31 15:14:47.000000000 +0100
++++ olsrd-0.5.4/lib/dyn_gw/src/olsrd_dyn_gw.c   2007-10-31 15:15:17.000000000 +0100
+@@ -92,7 +92,7 @@
+
+
+ /* set default interval, in case none is given in the config file */
+-static int check_interval = 5;
++static double check_interval = 5;
+
+ /* list to store the Ping IP addresses given in the config file */
+ struct ping_list {
+@@ -307,7 +307,7 @@
+     struct hna_list *li;
+     struct timespec remainder_spec;
+     /* the time to wait in "Interval" sec (see connfig), default=5sec */
+-    struct timespec sleeptime_spec  = { check_interval, 0L };
++    struct timespec sleeptime_spec  = { (int) check_interval, 0L };
+
+     for(li = the_hna_list; li; li = li->next){
+       /* check for gw in table entry and if Ping IPs are given also do pings */
diff -Nur kamikaze_7.09.orig/package/openssl/Makefile kamikaze_7.09/package/openssl/Makefile
--- kamikaze_7.09.orig/package/openssl/Makefile	2007-09-20 10:54:43.000000000 +0200
+++ kamikaze_7.09/package/openssl/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -7,6 +7,7 @@
 # $Id: Makefile 6892 2007-04-08 02:13:30Z pavlov $
 
 include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=openssl
 PKG_VERSION:=0.9.8e
@@ -33,6 +34,7 @@
 
 define Package/libopenssl
   $(call Package/openssl/Default)
+  SUBMENU:=openssl
   SECTION:=libs
   CATEGORY:=Libraries
   DEPENDS:=+zlib
@@ -58,11 +60,29 @@
 /etc/ssl/openssl.cnf
 endef
 
+define Package/libopenssl-cryptodev
+  SUBMENU:=openssl
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=Cryptodev support.
+  DEPENDS:=libopenssl
+endef
+
+define Package/libopenssl-cryptodev/description
+  Adds support for the cryptodev engine to libopenssl.
+endef
+
+
 OPENSSL_NO_CIPHERS:= no-idea no-md2 no-mdc2 no-rc2 no-rc5 no-sha0 no-smime \
 					no-rmd160 no-aes192 no-ripemd no-camellia no-ans1 no-krb5
 OPENSSL_OPTIONS:= shared no-ec no-err no-fips no-hw no-threads zlib-dynamic \
 					no-engines no-sse2 no-perlasm
 
+ifneq ($(SDK)$(CONFIG_PACKAGE_libopenssl-cryptodev),)
+  OPENSSL_OPTIONS:= shared no-ec no-err no-fips no-krb5 no-threads zlib-dynamic --with-cryptodev --with-cryptodev-digests
+  TARGET_CFLAGS+= -I$(LINUX_DIR)/crypto/ocf
+endif
+
 
 define Build/Configure
 	(cd $(PKG_BUILD_DIR); \
@@ -130,4 +150,5 @@
 endef
 
 $(eval $(call BuildPackage,libopenssl))
+$(eval $(call BuildPackage,libopenssl-cryptodev))
 $(eval $(call BuildPackage,openssl-util))
diff -Nur kamikaze_7.09.orig/package/openssl/patches/150-no_engines.patch kamikaze_7.09/package/openssl/patches/150-no_engines.patch
--- kamikaze_7.09.orig/package/openssl/patches/150-no_engines.patch	2007-09-20 10:54:43.000000000 +0200
+++ kamikaze_7.09/package/openssl/patches/150-no_engines.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,85 +0,0 @@
-Index: openssl-0.9.8e/util/libeay.num
-===================================================================
---- openssl-0.9.8e.orig/util/libeay.num	2007-06-04 13:23:32.021865832 +0200
-+++ openssl-0.9.8e/util/libeay.num	2007-06-04 13:23:33.045710184 +0200
-@@ -2071,7 +2071,6 @@
- UI_add_error_string                     2633	EXIST::FUNCTION:
- KRB5_CHECKSUM_free                      2634	EXIST::FUNCTION:
- OCSP_REQUEST_get_ext                    2635	EXIST::FUNCTION:
--ENGINE_load_ubsec                       2636	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- ENGINE_register_all_digests             2637	EXIST::FUNCTION:ENGINE
- PKEY_USAGE_PERIOD_it                    2638	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
- PKEY_USAGE_PERIOD_it                    2638	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
-@@ -2545,7 +2544,6 @@
- AES_set_encrypt_key                     3024	EXIST::FUNCTION:AES
- OCSP_resp_count                         3025	EXIST::FUNCTION:
- KRB5_CHECKSUM_new                       3026	EXIST::FUNCTION:
--ENGINE_load_cswift                      3027	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- OCSP_onereq_get0_id                     3028	EXIST::FUNCTION:
- ENGINE_set_default_ciphers              3029	EXIST::FUNCTION:ENGINE
- NOTICEREF_it                            3030	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
-@@ -2576,7 +2574,6 @@
- i2d_EXTENDED_KEY_USAGE                  3052	EXIST::FUNCTION:
- i2d_OCSP_SIGNATURE                      3053	EXIST::FUNCTION:
- asn1_enc_save                           3054	EXIST::FUNCTION:
--ENGINE_load_nuron                       3055	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- _ossl_old_des_pcbc_encrypt              3056	EXIST::FUNCTION:DES
- PKCS12_MAC_DATA_it                      3057	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
- PKCS12_MAC_DATA_it                      3057	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
-@@ -2600,7 +2597,6 @@
- i2d_KRB5_CHECKSUM                       3072	EXIST::FUNCTION:
- ENGINE_set_table_flags                  3073	EXIST::FUNCTION:ENGINE
- AES_options                             3074	EXIST::FUNCTION:AES
--ENGINE_load_chil                        3075	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- OCSP_id_cmp                             3076	EXIST::FUNCTION:
- OCSP_BASICRESP_new                      3077	EXIST::FUNCTION:
- OCSP_REQUEST_get_ext_by_NID             3078	EXIST::FUNCTION:
-@@ -2667,7 +2663,6 @@
- OCSP_CRLID_it                           3127	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
- i2d_KRB5_AUTHENTBODY                    3128	EXIST::FUNCTION:
- OCSP_REQUEST_get_ext_count              3129	EXIST::FUNCTION:
--ENGINE_load_atalla                      3130	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- X509_NAME_it                            3131	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
- X509_NAME_it                            3131	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
- USERNOTICE_it                           3132	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
-@@ -2762,8 +2757,6 @@
- DES_read_password                       3207	EXIST::FUNCTION:DES
- UI_UTIL_read_pw                         3208	EXIST::FUNCTION:
- UI_UTIL_read_pw_string                  3209	EXIST::FUNCTION:
--ENGINE_load_aep                         3210	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
--ENGINE_load_sureware                    3211	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- OPENSSL_add_all_algorithms_noconf       3212	EXIST:!VMS:FUNCTION:
- OPENSSL_add_all_algo_noconf             3212	EXIST:VMS:FUNCTION:
- OPENSSL_add_all_algorithms_conf         3213	EXIST:!VMS:FUNCTION:
-@@ -2772,7 +2765,6 @@
- AES_ofb128_encrypt                      3215	EXIST::FUNCTION:AES
- AES_ctr128_encrypt                      3216	EXIST::FUNCTION:AES
- AES_cfb128_encrypt                      3217	EXIST::FUNCTION:AES
--ENGINE_load_4758cca                     3218	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
- _ossl_096_des_random_seed               3219	EXIST::FUNCTION:DES
- EVP_aes_256_ofb                         3220	EXIST::FUNCTION:AES
- EVP_aes_192_ofb                         3221	EXIST::FUNCTION:AES
-@@ -3107,7 +3099,6 @@
- STORE_method_set_modify_function        3530	EXIST:!VMS:FUNCTION:
- STORE_meth_set_modify_fn                3530	EXIST:VMS:FUNCTION:
- STORE_parse_attrs_next                  3531	EXIST::FUNCTION:
--ENGINE_load_padlock                     3532	EXIST::FUNCTION:ENGINE
- EC_GROUP_set_curve_name                 3533	EXIST::FUNCTION:EC
- X509_CERT_PAIR_it                       3534	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
- X509_CERT_PAIR_it                       3534	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
-Index: openssl-0.9.8e/Configure
-===================================================================
---- openssl-0.9.8e.orig/Configure	2007-06-04 13:23:32.598778128 +0200
-+++ openssl-0.9.8e/Configure	2007-06-04 13:23:33.046710032 +0200
-@@ -1644,6 +1644,11 @@
- 	close(OUT);
-   }
-   
-+# ugly hack to disable engines
-+if($target eq "mingwx") {
-+	system("sed -e s/^LIB/XLIB/g -i engines/Makefile");
-+}
-+  
- print <<EOF;
- 
- Configured for $target.
diff -Nur kamikaze_7.09.orig/package/openssl/patches/190-linux_ocf.patch kamikaze_7.09/package/openssl/patches/190-linux_ocf.patch
--- kamikaze_7.09.orig/package/openssl/patches/190-linux_ocf.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/openssl/patches/190-linux_ocf.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,1229 @@
+diff -urN openssl-0.9.8e.old/apps/apps.h openssl-0.9.8e/apps/apps.h
+--- openssl-0.9.8e.old/apps/apps.h	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/apps/apps.h	2008-02-26 10:31:12.000000000 -0500
+@@ -112,7 +112,7 @@
+ #ifndef HEADER_APPS_H
+ #define HEADER_APPS_H
+ 
+-#include "e_os.h"
++#include <openssl/e_os.h>
+ 
+ #include <openssl/bio.h>
+ #include <openssl/x509.h>
+diff -urN openssl-0.9.8e.old/apps/progs.h openssl-0.9.8e/apps/progs.h
+--- openssl-0.9.8e.old/apps/progs.h	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/apps/progs.h	2008-02-26 10:31:12.000000000 -0500
+@@ -125,7 +125,9 @@
+ #ifndef OPENSSL_NO_ENGINE
+ 	{FUNC_TYPE_GENERAL,"engine",engine_main},
+ #endif
++#ifndef OPENSSL_NO_OCSP
+ 	{FUNC_TYPE_GENERAL,"ocsp",ocsp_main},
++#endif
+ 	{FUNC_TYPE_GENERAL,"prime",prime_main},
+ #ifndef OPENSSL_NO_MD2
+ 	{FUNC_TYPE_MD,"md2",dgst_main},
+diff -urN openssl-0.9.8e.old/apps/speed.c openssl-0.9.8e/apps/speed.c
+--- openssl-0.9.8e.old/apps/speed.c	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/apps/speed.c	2008-02-26 10:31:12.000000000 -0500
+@@ -288,7 +288,7 @@
+   "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc",
+   "evp","sha256","sha512"};
+ static double results[ALGOR_NUM][SIZE_NUM];
+-static int lengths[SIZE_NUM]={16,64,256,1024,8*1024};
++static int lengths[SIZE_NUM]={16,64,256,1024,2*1024,4*1024};
+ static double rsa_results[RSA_NUM][2];
+ static double dsa_results[DSA_NUM][2];
+ #ifndef OPENSSL_NO_ECDSA
+@@ -324,6 +324,79 @@
+ #define START	0
+ #define STOP	1
+ 
++#ifdef __linux__
++/*
++ * record CPU usage as well
++ */
++
++static int do_cpu = 0;
++
++struct cpu_stat {
++	unsigned int	user;
++	unsigned int	nice;
++	unsigned int	system;
++	unsigned int	idle;
++	unsigned int	total;
++};
++
++static unsigned int cpu_usage[ALGOR_NUM][SIZE_NUM];
++static unsigned int rsa_cpu_usage[RSA_NUM][2];
++static unsigned int dsa_cpu_usage[DSA_NUM][2];
++static struct cpu_stat cpu_start, cpu_finish;
++
++static void
++get_cpu(int s)
++{
++	FILE *fp = NULL;
++	unsigned char	buf[80];
++	struct cpu_stat *st = s == START ? &cpu_start : &cpu_finish;
++
++	memset(st, 0, sizeof(*st));
++
++	if (fp == NULL)
++		fp = fopen("/proc/stat", "r");
++	if (!fp)
++		return;
++	if (fseek(fp, 0, SEEK_SET) == -1) {
++		fclose(fp);
++		return;
++	}
++	fscanf(fp, "%s %d %d %d %d", &buf[0], &st->user, &st->nice,
++		&st->system, &st->idle);
++	st->total = st->user + st->nice + st->system + st->idle;
++	fclose(fp);
++}
++
++static unsigned int
++calc_cpu()
++{
++	unsigned int total, res;
++
++	total  = cpu_finish.total - cpu_start.total;
++	if (total <= 0)
++		return 0;
++#if 1 // busy
++	res   = ((cpu_finish.system + cpu_finish.user + cpu_finish.nice) -
++			 (cpu_start.system + cpu_start.user + cpu_start.nice)) *
++			 100 / total;
++#endif
++#if 0 // system
++	res   = (cpu_finish.system - cpu_start.system) * 100 / total;
++#endif
++#if 0 // user
++	res   = (cpu_finish.user   - cpu_start.user)   * 100 / total;
++#endif
++#if 0 // nice
++	res   = (cpu_finish.nice   - cpu_start.nice)   * 100 / total;
++#endif
++#if 0 // idle
++	res   = (cpu_finish.idle   - cpu_start.idle)   * 100 / total;
++#endif
++	return(res);
++}
++
++#endif
++
+ #if defined(OPENSSL_SYS_NETWARE)
+ 
+    /* for NetWare the best we can do is use clock() which returns the
+@@ -354,6 +427,11 @@
+ 	{
+ 	double ret;
+ 
++#ifdef __linux__
++	if (do_cpu)
++		get_cpu(s);
++#endif
++
+ #ifdef USE_TOD
+ 	if(usertime)
+ 		{
+@@ -821,6 +899,14 @@
+ 			j--;	/* Otherwise, -elapsed gets confused with
+ 				   an algorithm. */
+ 			}
++#ifdef __linux__
++		else if	((argc > 0) && (strcmp(*argv,"-cpu") == 0))
++			{
++			do_cpu = 1;
++			j--;	/* Otherwise, -cpu gets confused with
++				   an algorithm. */
++			}
++#endif
+ 		else if	((argc > 0) && (strcmp(*argv,"-evp") == 0))
+ 			{
+ 			argc--;
+@@ -1234,6 +1320,9 @@
+ #ifdef HAVE_FORK
+ 			BIO_printf(bio_err,"-multi n        run n benchmarks in parallel.\n");
+ #endif
++#ifdef __linux__
++			BIO_printf(bio_err,"-cpu            calculate cpu utilisation.\n");
++#endif
+ 			goto end;
+ 			}
+ 		argc--;
+@@ -1241,11 +1330,6 @@
+ 		j++;
+ 		}
+ 
+-#ifdef HAVE_FORK
+-	if(multi && do_multi(multi))
+-		goto show_res;
+-#endif
+-
+ 	if (j == 0)
+ 		{
+ 		for (i=0; i<ALGOR_NUM; i++)
+@@ -1567,6 +1651,11 @@
+ 	signal(SIGALRM,sig_done);
+ #endif /* SIGALRM */
+ 
++#ifdef HAVE_FORK /* DM */
++	if(multi && do_multi(multi))
++		goto show_res;
++#endif
++
+ #ifndef OPENSSL_NO_MD2
+ 	if (doit[D_MD2])
+ 		{
+@@ -1939,8 +2028,6 @@
+ 				/* -O3 -fschedule-insns messes up an
+ 				 * optimization here!  names[D_EVP]
+ 				 * somehow becomes NULL */
+-				print_message(names[D_EVP],save_count,
+-					lengths[j]);
+ 
+ 				EVP_CIPHER_CTX_init(&ctx);
+ 				if(decrypt)
+@@ -1949,6 +2036,9 @@
+ 					EVP_EncryptInit_ex(&ctx,evp_cipher,NULL,key16,iv);
+ 				EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ 
++				print_message(names[D_EVP],save_count,
++					lengths[j]);
++
+ 				Time_F(START);
+ 				if(decrypt)
+ 					for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+@@ -2013,6 +2103,8 @@
+ 					}
+ 				}
+ 			d=Time_F(STOP);
++			if (do_cpu)
++				rsa_cpu_usage[j][0] = calc_cpu();
+ 			BIO_printf(bio_err,mr ? "+R1:%ld:%d:%.2f\n"
+ 				   : "%ld %d bit private RSA's in %.2fs\n",
+ 				   count,rsa_bits[j],d);
+@@ -2048,6 +2140,8 @@
+ 					}
+ 				}
+ 			d=Time_F(STOP);
++			if (do_cpu)
++				rsa_cpu_usage[j][1] = calc_cpu();
+ 			BIO_printf(bio_err,mr ? "+R2:%ld:%d:%.2f\n"
+ 				   : "%ld %d bit public RSA's in %.2fs\n",
+ 				   count,rsa_bits[j],d);
+@@ -2107,6 +2201,8 @@
+ 					}
+ 				}
+ 			d=Time_F(STOP);
++			if (do_cpu)
++				dsa_cpu_usage[j][0] = calc_cpu();
+ 			BIO_printf(bio_err,mr ? "+R3:%ld:%d:%.2f\n"
+ 				   : "%ld %d bit DSA signs in %.2fs\n",
+ 				   count,dsa_bits[j],d);
+@@ -2142,6 +2238,8 @@
+ 					}
+ 				}
+ 			d=Time_F(STOP);
++			if (do_cpu)
++				dsa_cpu_usage[j][1] = calc_cpu();
+ 			BIO_printf(bio_err,mr ? "+R4:%ld:%d:%.2f\n"
+ 				   : "%ld %d bit DSA verify in %.2fs\n",
+ 				   count,dsa_bits[j],d);
+@@ -2436,14 +2534,23 @@
+ 			fprintf(stdout,"The 'numbers' are in 1000s of bytes per second processed.\n"); 
+ 			fprintf(stdout,"type        ");
+ 			}
+-		for (j=0;  j<SIZE_NUM; j++)
++		for (j=0;  j<SIZE_NUM; j++) {
+ 			fprintf(stdout,mr ? ":%d" : "%7d bytes",lengths[j]);
++			if (do_cpu && !mr)
++				fprintf(stdout, " /cpu");
++		}
+ 		fprintf(stdout,"\n");
+ 		}
+ 
+ 	for (k=0; k<ALGOR_NUM; k++)
+ 		{
+ 		if (!doit[k]) continue;
++		if (k == D_EVP) {
++			if (evp_cipher)
++				names[D_EVP]=OBJ_nid2ln(evp_cipher->nid);
++			else
++				names[D_EVP]=OBJ_nid2ln(evp_md->type);
++		}
+ 		if(mr)
+ 			fprintf(stdout,"+F:%d:%s",k,names[k]);
+ 		else
+@@ -2454,6 +2561,8 @@
+ 				fprintf(stdout," %11.2fk",results[k][j]/1e3);
+ 			else
+ 				fprintf(stdout,mr ? ":%.2f" : " %11.2f ",results[k][j]);
++			if (do_cpu)
++				fprintf(stdout, mr ? "/%d" : "/%%%-3d", cpu_usage[k][j]);
+ 			}
+ 		fprintf(stdout,"\n");
+ 		}
+@@ -2468,13 +2577,18 @@
+ 			j=0;
+ 			}
+ 		if(mr)
+-			fprintf(stdout,"+F2:%u:%u:%f:%f\n",
+-				k,rsa_bits[k],rsa_results[k][0],
+-				rsa_results[k][1]);
+-		else
+-			fprintf(stdout,"rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+-				rsa_bits[k],rsa_results[k][0],rsa_results[k][1],
+-				1.0/rsa_results[k][0],1.0/rsa_results[k][1]);
++			fprintf(stdout,"+F2:%u:%u:%f", k,rsa_bits[k],rsa_results[k][0]);
++		else
++			fprintf(stdout,"rsa %4u bits %8.6fs",rsa_bits[k],rsa_results[k][0]);
++		if (do_cpu)
++			fprintf(stdout, mr ? "/%d": "/%%%-3d", rsa_cpu_usage[k][0]);
++		fprintf(stdout, mr ? ":%f" : " %8.6fs", rsa_results[k][1]);
++		if (do_cpu)
++			fprintf(stdout, mr ? "/%d": "/%%%-3d", rsa_cpu_usage[k][1]);
++		if(!mr)
++			fprintf(stdout, " %8.1f %8.1f",
++					1.0/rsa_results[k][0],1.0/rsa_results[k][1]);
++		fprintf(stdout, "\n");
+ 		}
+ #endif
+ #ifndef OPENSSL_NO_DSA
+@@ -2488,12 +2602,18 @@
+ 			j=0;
+ 			}
+ 		if(mr)
+-			fprintf(stdout,"+F3:%u:%u:%f:%f\n",
+-				k,dsa_bits[k],dsa_results[k][0],dsa_results[k][1]);
++			fprintf(stdout,"+F3:%u:%u:%f", k,dsa_bits[k],dsa_results[k][0]);
+ 		else
+-			fprintf(stdout,"dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+-				dsa_bits[k],dsa_results[k][0],dsa_results[k][1],
+-				1.0/dsa_results[k][0],1.0/dsa_results[k][1]);
++			fprintf(stdout,"dsa %4u bits %8.6fs",dsa_bits[k],dsa_results[k][0]);
++		if (do_cpu)
++			fprintf(stdout, mr ? "/%d": "/%%%-3d", dsa_cpu_usage[k][0]);
++		fprintf(stdout, mr ? ":%f" : " %8.6fs", dsa_results[k][1]);
++		if (do_cpu)
++			fprintf(stdout, mr ? "/%d": "/%%%-3d", dsa_cpu_usage[k][1]);
++		if(!mr)
++			fprintf(stdout, " %8.1f %8.1f",
++					1.0/dsa_results[k][0],1.0/dsa_results[k][1]);
++		fprintf(stdout, "\n");
+ 		}
+ #endif
+ #ifndef OPENSSL_NO_ECDSA
+@@ -2618,8 +2738,10 @@
+ 
+ static void print_result(int alg,int run_no,int count,double time_used)
+ 	{
+-	BIO_printf(bio_err,mr ? "+R:%d:%s:%f\n"
+-		   : "%d %s's in %.2fs\n",count,names[alg],time_used);
++	if (do_cpu)
++	    cpu_usage[alg][run_no] = calc_cpu();
++	BIO_printf(bio_err,mr ? "+R:%ld:%s:%f\n"
++		   : "%ld %s's in %.2fs\n",count,names[alg],time_used);
+ 	results[alg][run_no]=((double)count)/time_used*lengths[run_no];
+ 	}
+ 
+@@ -2712,29 +2834,11 @@
+ 				p=buf+3;
+ 				alg=atoi(sstrsep(&p,sep));
+ 				sstrsep(&p,sep);
+-				for(j=0 ; j < SIZE_NUM ; ++j)
++				for(j=0 ; j < SIZE_NUM ; ++j) {
++					if (do_cpu && strchr(p, '/'))
++						cpu_usage[alg][j] = atoi(strchr(p, '/') + 1);
+ 					results[alg][j]+=atof(sstrsep(&p,sep));
+ 				}
+-			else if(!strncmp(buf,"+F2:",4))
+-				{
+-				int k;
+-				double d;
+-				
+-				p=buf+4;
+-				k=atoi(sstrsep(&p,sep));
+-				sstrsep(&p,sep);
+-
+-				d=atof(sstrsep(&p,sep));
+-				if(n)
+-					rsa_results[k][0]=1/(1/rsa_results[k][0]+1/d);
+-				else
+-					rsa_results[k][0]=d;
+-
+-				d=atof(sstrsep(&p,sep));
+-				if(n)
+-					rsa_results[k][1]=1/(1/rsa_results[k][1]+1/d);
+-				else
+-					rsa_results[k][1]=d;
+ 				}
+ 			else if(!strncmp(buf,"+F2:",4))
+ 				{
+@@ -2745,12 +2849,18 @@
+ 				k=atoi(sstrsep(&p,sep));
+ 				sstrsep(&p,sep);
+ 
++				/* before we move the token along */
++				if (do_cpu && strchr(p, '/'))
++					rsa_cpu_usage[k][0] = atoi(strchr(p, '/') + 1);
+ 				d=atof(sstrsep(&p,sep));
+ 				if(n)
+ 					rsa_results[k][0]=1/(1/rsa_results[k][0]+1/d);
+ 				else
+ 					rsa_results[k][0]=d;
+ 
++				/* before we move the token along */
++				if (do_cpu && strchr(p, '/'))
++					rsa_cpu_usage[k][1] = atoi(strchr(p, '/') + 1);
+ 				d=atof(sstrsep(&p,sep));
+ 				if(n)
+ 					rsa_results[k][1]=1/(1/rsa_results[k][1]+1/d);
+@@ -2766,12 +2876,18 @@
+ 				k=atoi(sstrsep(&p,sep));
+ 				sstrsep(&p,sep);
+ 
++				/* before we move the token along */
++				if (do_cpu && strchr(p, '/'))
++					dsa_cpu_usage[k][0] = atoi(strchr(p, '/') + 1);
+ 				d=atof(sstrsep(&p,sep));
+ 				if(n)
+ 					dsa_results[k][0]=1/(1/dsa_results[k][0]+1/d);
+ 				else
+ 					dsa_results[k][0]=d;
+ 
++				/* before we move the token along */
++				if (do_cpu && strchr(p, '/'))
++					dsa_cpu_usage[k][1] = atoi(strchr(p, '/') + 1);
+ 				d=atof(sstrsep(&p,sep));
+ 				if(n)
+ 					dsa_results[k][1]=1/(1/dsa_results[k][1]+1/d);
+diff -urN openssl-0.9.8e.old/config openssl-0.9.8e/config
+--- openssl-0.9.8e.old/config	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/config	2008-02-26 10:31:12.000000000 -0500
+@@ -48,10 +48,10 @@
+ 
+ # First get uname entries that we use below
+ 
+-MACHINE=`(uname -m) 2>/dev/null` || MACHINE="unknown"
+-RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown"
+-SYSTEM=`(uname -s) 2>/dev/null`  || SYSTEM="unknown"
+-VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown"
++[ "$MACHINE" ] || MACHINE=`(uname -m) 2>/dev/null` || MACHINE="unknown"
++[ "$RELEASE" ] || RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown"
++[ "$SYSTEM" ]  || SYSTEM=`(uname -s) 2>/dev/null`  || SYSTEM="unknown"
++[ "$VERSION" ] || VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown"
+ 
+ 
+ # Now test for ISC and SCO, since it is has a braindamaged uname.
+@@ -270,7 +270,7 @@
+ 		echo "ppc-apple-darwin${VERSION}"
+ 		;;
+ 	    *)
+-		echo "i386-apple-darwin${VERSION}"
++		echo "${MACHINE}-apple-darwin${VERSION}"
+ 		;;
+ 	esac
+ 	exit 0
+@@ -401,9 +401,9 @@
+ 
+ # figure out if gcc is available and if so we use it otherwise
+ # we fallback to whatever cc does on the system
+-GCCVER=`(gcc -dumpversion) 2>/dev/null`
++CC="${CC:-gcc}"
++GCCVER=`(${CC} -dumpversion) 2>/dev/null`
+ if [ "$GCCVER" != "" ]; then
+-  CC=gcc
+   # then strip off whatever prefix egcs prepends the number with...
+   # Hopefully, this will work for any future prefixes as well.
+   GCCVER=`echo $GCCVER | LC_ALL=C sed 's/^[a-zA-Z]*\-//'`
+@@ -413,7 +413,7 @@
+   # peak single digit before and after first dot, e.g. 2.95.1 gives 29
+   GCCVER=`echo $GCCVER | sed 's/\([0-9]\)\.\([0-9]\).*/\1\2/'`
+ else
+-  CC=cc
++  CC="${CC:-cc}"
+ fi
+ GCCVER=${GCCVER:-0}
+ if [ "$SYSTEM" = "HP-UX" ];then
+@@ -482,6 +482,9 @@
+ # script above so we end up with values in vars but that would take
+ # more time that I want to waste at the moment
+ case "$GUESSOS" in
++  uClinux*)
++    OUT=uClinux-dist
++	;;
+   mips2-sgi-irix)
+ 	CPU=`(hinv -t cpu) 2>/dev/null | head -1 | sed 's/^CPU:[^R]*R\([0-9]*\).*/\1/'`
+ 	CPU=${CPU:-0}
+diff -urN openssl-0.9.8e.old/Configure openssl-0.9.8e/Configure
+--- openssl-0.9.8e.old/Configure	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/Configure	2008-02-26 10:31:12.000000000 -0500
+@@ -34,6 +34,8 @@
+ #		(Default: KRB5_DIR/include)
+ # --with-krb5-flavor  Declare what flavor of Kerberos 5 is used.  Currently
+ #		supported values are "MIT" and "Heimdal".  A value is required.
++# --with-cryptodev Force support for cryptodev (ie., ocf-linux)
++# --with-cryptodev-digests Force support for cryptodev digests (generally slow)
+ #
+ # --test-sanity Make a number of sanity checks on the data in this file.
+ #               This is a debugging tool for OpenSSL developers.
+@@ -528,6 +530,9 @@
+ ##### Compaq Non-Stop Kernel (Tandem)
+ "tandem-c89","c89:-Ww -D__TANDEM -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1 -D_TANDEM_SOURCE -DB_ENDIAN::(unknown):::THIRTY_TWO_BIT:::",
+ 
++# uClinux
++"uClinux-dist","$ENV{'CC'}:\$(CFLAGS)::-D_REENTRANT::\$(LDFLAGS) \$(LDLIBS):BN_LLONG::::::::::::\$(LIBSSL_dlfcn):linux-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):$ENV{'RANLIB'}",
++
+ );
+ 
+ my @MK1MF_Builds=qw(VC-WIN64I VC-WIN64A
+@@ -574,6 +579,8 @@
+ my $no_asm=0;
+ my $no_dso=0;
+ my $no_gmp=0;
++my $have_cryptodev=0;
++my $use_cryptodev_digests=0;
+ my @skip=();
+ my $Makefile="Makefile";
+ my $des_locl="crypto/des/des_locl.h";
+@@ -696,6 +703,14 @@
+ 			{
+ 			exit(&test_sanity());
+ 			}
++		elsif (/^--with-cryptodev$/)
++			{
++				$have_cryptodev = 1;
++			}
++		elsif (/^--with-cryptodev-digests$/)
++			{
++				$use_cryptodev_digests = 1;
++			}
+ 		elsif (/^reconfigure/ || /^reconf/)
+ 			{
+ 			if (open(IN,"<$Makefile"))
+@@ -898,6 +913,7 @@
+ 			print " OPENSSL_NO_$ALGO";
+ 		
+ 			if (/^err$/)	{ $flags .= "-DOPENSSL_NO_ERR "; }
++			elsif (/^hw$/)	{ $flags .= "-DOPENSSL_NO_HW "; }
+ 			elsif (/^asm$/)	{ $no_asm = 1; }
+ 			}
+ 		else
+@@ -1032,6 +1048,16 @@
+ 		   $withargs{"krb5-dir"} ne "";
+ 	}
+ 
++# enable the linux cryptodev (ocf-linux) support
++if ($have_cryptodev)
++	{
++	if ($use_cryptodev_digests)
++		{
++		$cflags = "-DUSE_CRYPTODEV_DIGESTS $cflags";
++		}
++	$cflags = "-DHAVE_CRYPTODEV $cflags";
++	}
++
+ # The DSO code currently always implements all functions so that no
+ # applications will have to worry about that from a compilation point
+ # of view. However, the "method"s may return zero unless that platform
+diff -urN openssl-0.9.8e.old/crypto/cryptlib.h openssl-0.9.8e/crypto/cryptlib.h
+--- openssl-0.9.8e.old/crypto/cryptlib.h	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/cryptlib.h	2008-02-26 10:31:12.000000000 -0500
+@@ -62,7 +62,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#include "e_os.h"
++#include <openssl/e_os.h>
+ 
+ #ifdef OPENSSL_USE_APPLINK
+ #define BIO_FLAGS_UPLINK 0x8000
+diff -urN openssl-0.9.8e.old/crypto/engine/eng_all.c openssl-0.9.8e/crypto/engine/eng_all.c
+--- openssl-0.9.8e.old/crypto/engine/eng_all.c	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/engine/eng_all.c	2008-02-26 10:31:12.000000000 -0500
+@@ -104,13 +104,13 @@
+ #endif
+ #endif
+ #ifndef OPENSSL_NO_HW
+-#if defined(__OpenBSD__) || defined(__FreeBSD__)
++#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+ 	ENGINE_load_cryptodev();
+ #endif
+ #endif
+ 	}
+ 
+-#if defined(__OpenBSD__) || defined(__FreeBSD__)
++#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+ void ENGINE_setup_bsd_cryptodev(void) {
+ 	static int bsd_cryptodev_default_loaded = 0;
+ 	if (!bsd_cryptodev_default_loaded) {
+diff -urN openssl-0.9.8e.old/crypto/engine/eng_cryptodev.c openssl-0.9.8e/crypto/engine/eng_cryptodev.c
+--- openssl-0.9.8e.old/crypto/engine/eng_cryptodev.c	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/engine/eng_cryptodev.c	2008-02-26 10:31:12.000000000 -0500
+@@ -68,6 +68,16 @@
+ struct dev_crypto_state {
+ 	struct session_op d_sess;
+ 	int d_fd;
++
++#ifdef USE_CRYPTODEV_DIGESTS
++	char dummy_mac_key[20];
++
++	unsigned char digest_res[20];
++	char *mac_data;
++	int mac_len;
++
++	int copy;
++#endif
+ };
+ 
+ static u_int32_t cryptodev_asymfeat = 0;
+@@ -75,9 +85,11 @@
+ static int get_asym_dev_crypto(void);
+ static int open_dev_crypto(void);
+ static int get_dev_crypto(void);
++#if 0
+ static int cryptodev_max_iv(int cipher);
+ static int cryptodev_key_length_valid(int cipher, int len);
+ static int cipher_nid_to_cryptodev(int nid);
++#endif
+ static int get_cryptodev_ciphers(const int **cnids);
+ static int get_cryptodev_digests(const int **cnids);
+ static int cryptodev_usable_ciphers(const int **nids);
+@@ -100,7 +112,7 @@
+ static int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a,
+     const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+ static int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I,
+-    RSA *rsa);
++    RSA *rsa, BN_CTX *ctx);
+ static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+ static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a,
+     const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+@@ -133,6 +145,7 @@
+ 	{ CRYPTO_DES_CBC,		NID_des_cbc,		8,	 8, },
+ 	{ CRYPTO_3DES_CBC,		NID_des_ede3_cbc,	8,	24, },
+ 	{ CRYPTO_AES_CBC,		NID_aes_128_cbc,	16,	16, },
++	{ CRYPTO_AES_CBC,		NID_aes_256_cbc,	16,	32, },
+ 	{ CRYPTO_BLF_CBC,		NID_bf_cbc,		8,	16, },
+ 	{ CRYPTO_CAST_CBC,		NID_cast5_cbc,		8,	16, },
+ 	{ CRYPTO_SKIPJACK_CBC,		NID_undef,		0,	 0, },
+@@ -142,14 +155,15 @@
+ static struct {
+ 	int	id;
+ 	int	nid;
++	int 	keylen;
+ } digests[] = {
+-	{ CRYPTO_SHA1_HMAC,		NID_hmacWithSHA1,	},
+-	{ CRYPTO_RIPEMD160_HMAC,	NID_ripemd160,		},
+-	{ CRYPTO_MD5_KPDK,		NID_undef,		},
+-	{ CRYPTO_SHA1_KPDK,		NID_undef,		},
+-	{ CRYPTO_MD5,			NID_md5,		},
+-	{ CRYPTO_SHA1,			NID_undef,		},
+-	{ 0,				NID_undef,		},
++	{ CRYPTO_SHA1_HMAC,		NID_hmacWithSHA1,	20},
++	{ CRYPTO_RIPEMD160_HMAC,	NID_ripemd160,		16/*?*/},
++	{ CRYPTO_MD5_KPDK,		NID_undef,		0},
++	{ CRYPTO_SHA1_KPDK,		NID_undef,		0},
++	{ CRYPTO_MD5,			NID_md5,		16},
++	{ CRYPTO_SHA1,			NID_sha1,		20},
++	{ 0,				NID_undef,		0},
+ };
+ 
+ /*
+@@ -176,10 +190,17 @@
+ static int
+ get_dev_crypto(void)
+ {
+-	int fd, retfd;
++	static int fd = -1;
++	int retfd;
+ 
+-	if ((fd = open_dev_crypto()) == -1)
+-		return (-1);
++	if (fd == -1) {
++		if ((fd = open_dev_crypto()) == -1)
++			return (-1);
++		if (fcntl(fd, F_SETFD, 1) == -1) {
++			close(fd);
++			return (-1);
++		}
++	}
+ 	if (ioctl(fd, CRIOGET, &retfd) == -1)
+ 		return (-1);
+ 
+@@ -202,6 +223,7 @@
+ 	return fd;
+ }
+ 
++#if 0
+ /*
+  * XXXX this needs to be set for each alg - and determined from
+  * a running card.
+@@ -245,6 +267,7 @@
+ 			return (ciphers[i].id);
+ 	return (0);
+ }
++#endif
+ 
+ /*
+  * Find out what ciphers /dev/crypto will let us have a session for.
+@@ -264,7 +287,7 @@
+ 		return (0);
+ 	}
+ 	memset(&sess, 0, sizeof(sess));
+-	sess.key = (caddr_t)"123456781234567812345678";
++	sess.key = (caddr_t)"123456789abcdefghijklmno";
+ 
+ 	for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+ 		if (ciphers[i].nid == NID_undef)
+@@ -303,10 +326,12 @@
+ 		return (0);
+ 	}
+ 	memset(&sess, 0, sizeof(sess));
++	sess.mackey = (caddr_t)"123456789abcdefghijklmno";
+ 	for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+ 		if (digests[i].nid == NID_undef)
+ 			continue;
+ 		sess.mac = digests[i].id;
++		sess.mackeylen = digests[i].keylen;
+ 		sess.cipher = 0;
+ 		if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
+ 		    ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+@@ -351,6 +376,9 @@
+ static int
+ cryptodev_usable_digests(const int **nids)
+ {
++#ifdef USE_CRYPTODEV_DIGESTS
++	return (get_cryptodev_digests(nids));
++#else
+ 	/*
+ 	 * XXXX just disable all digests for now, because it sucks.
+ 	 * we need a better way to decide this - i.e. I may not
+@@ -365,6 +393,7 @@
+ 	 */
+ 	*nids = NULL;
+ 	return (0);
++#endif
+ }
+ 
+ static int
+@@ -427,16 +456,20 @@
+ {
+ 	struct dev_crypto_state *state = ctx->cipher_data;
+ 	struct session_op *sess = &state->d_sess;
+-	int cipher;
+-
+-	if ((cipher = cipher_nid_to_cryptodev(ctx->cipher->nid)) == NID_undef)
+-		return (0);
++	int cipher, i;
+ 
+-	if (ctx->cipher->iv_len > cryptodev_max_iv(cipher))
+-		return (0);
++	for (i = 0; ciphers[i].id; i++)
++		if (ctx->cipher->nid == ciphers[i].nid &&
++		    ctx->cipher->iv_len <= ciphers[i].ivmax &&
++		    ctx->key_len == ciphers[i].keylen) {
++			cipher = ciphers[i].id;
++			break;
++		}
+ 
+-	if (!cryptodev_key_length_valid(cipher, ctx->key_len))
++	if (!ciphers[i].id) {
++		state->d_fd = -1;
+ 		return (0);
++	}
+ 
+ 	memset(sess, 0, sizeof(struct session_op));
+ 
+@@ -563,6 +596,19 @@
+ 	NULL
+ };
+ 
++const EVP_CIPHER cryptodev_aes_256_cbc = {
++	NID_aes_256_cbc,
++	16, 32, 16,
++	EVP_CIPH_CBC_MODE,
++	cryptodev_init_key,
++	cryptodev_cipher,
++	cryptodev_cleanup,
++	sizeof(struct dev_crypto_state),
++	EVP_CIPHER_set_asn1_iv,
++	EVP_CIPHER_get_asn1_iv,
++	NULL
++};
++
+ /*
+  * Registered by the ENGINE when used to find out how to deal with
+  * a particular NID in the ENGINE. this says what we'll do at the
+@@ -591,6 +637,9 @@
+ 	case NID_aes_128_cbc:
+ 		*cipher = &cryptodev_aes_cbc;
+ 		break;
++	case NID_aes_256_cbc:
++		*cipher = &cryptodev_aes_256_cbc;
++		break;
+ 	default:
+ 		*cipher = NULL;
+ 		break;
+@@ -598,6 +647,234 @@
+ 	return (*cipher != NULL);
+ }
+ 
++
++#ifdef USE_CRYPTODEV_DIGESTS
++
++/* convert digest type to cryptodev */
++static int
++digest_nid_to_cryptodev(int nid)
++{
++	int i;
++
++	for (i = 0; digests[i].id; i++)
++		if (digests[i].nid == nid)
++			return (digests[i].id);
++	return (0);
++}
++
++
++static int
++digest_key_length(int nid)
++{
++	int i;
++
++	for (i = 0; digests[i].id; i++)
++		if (digests[i].nid == nid)
++			return digests[i].keylen;
++	return (0);
++}
++
++
++static int cryptodev_digest_init(EVP_MD_CTX *ctx)
++{
++	struct dev_crypto_state *state = ctx->md_data;
++	struct session_op *sess = &state->d_sess;
++	int digest;
++
++	if ((digest = digest_nid_to_cryptodev(ctx->digest->type)) == NID_undef){
++		printf("cryptodev_digest_init: Can't get digest \n");
++		return (0);
++	}
++
++	memset(state, 0, sizeof(struct dev_crypto_state));
++
++	if ((state->d_fd = get_dev_crypto()) < 0) {
++		printf("cryptodev_digest_init: Can't get Dev \n");
++		return (0);
++	}
++
++	sess->mackey = state->dummy_mac_key;
++	sess->mackeylen = digest_key_length(ctx->digest->type);
++	sess->mac = digest;
++
++	if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
++		close(state->d_fd);
++		state->d_fd = -1;
++		printf("cryptodev_digest_init: Open session failed\n");
++		return (0);
++	}
++
++	return (1);
++}
++
++static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
++		size_t count)
++{
++	struct crypt_op cryp;
++	struct dev_crypto_state *state = ctx->md_data;
++	struct session_op *sess = &state->d_sess;
++
++	if (!data || state->d_fd < 0) {
++		printf("cryptodev_digest_update: illegal inputs \n");
++		return (0);
++	}
++
++	if (!count) {
++		return (0);
++	}
++
++	if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) {
++		/* if application doesn't support one buffer */
++		state->mac_data = OPENSSL_realloc(state->mac_data, state->mac_len + count);
++
++		if (!state->mac_data) {
++			printf("cryptodev_digest_update: realloc failed\n");
++			return (0);
++		}
++
++		memcpy(state->mac_data + state->mac_len, data, count);
++   		state->mac_len += count;
++	
++		return (1);
++	}
++
++	memset(&cryp, 0, sizeof(cryp));
++
++	cryp.ses = sess->ses;
++	cryp.flags = 0;
++	cryp.len = count;
++	cryp.src = (caddr_t) data;
++	cryp.dst = NULL;
++	cryp.mac = state->digest_res;
++	if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
++		printf("cryptodev_digest_update: digest failed\n");
++		return (0);
++	}
++	return (1);
++}
++
++
++static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++	struct crypt_op cryp;
++	struct dev_crypto_state *state = ctx->md_data;
++	struct session_op *sess = &state->d_sess;
++
++	int ret = 1;
++
++	if (!md || state->d_fd < 0) {
++		printf("cryptodev_digest_final: illegal input\n");
++		return(0);
++	}
++
++	if (! (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) ) {
++		/* if application doesn't support one buffer */
++		memset(&cryp, 0, sizeof(cryp));
++
++		cryp.ses = sess->ses;
++		cryp.flags = 0;
++		cryp.len = state->mac_len;
++		cryp.src = state->mac_data;
++		cryp.dst = NULL;
++		cryp.mac = md;
++
++		if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
++			printf("cryptodev_digest_final: digest failed\n");
++			return (0);
++		}
++
++		return 1;
++	}
++
++	memcpy(md, state->digest_res, ctx->digest->md_size);
++
++	return (ret);
++}
++
++
++static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
++{
++	int ret = 1;
++	struct dev_crypto_state *state = ctx->md_data;
++	struct session_op *sess = &state->d_sess;
++
++	if (state->d_fd < 0) {
++		printf("cryptodev_digest_cleanup: illegal input\n");
++		return (0);
++	}
++
++	if (state->mac_data) {
++		OPENSSL_free(state->mac_data);
++		state->mac_data = NULL;
++		state->mac_len = 0;
++	}
++
++	if (state->copy)
++		return 1;
++
++	if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
++		printf("cryptodev_digest_cleanup: failed to close session\n");
++		ret = 0;
++	} else {
++		ret = 1;
++	}
++	close(state->d_fd);	
++	state->d_fd = -1;
++
++	return (ret);
++}
++
++static int cryptodev_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
++{
++	struct dev_crypto_state *fstate = from->md_data;
++	struct dev_crypto_state *dstate = to->md_data;
++
++	memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
++
++	if (fstate->mac_len != 0) {
++		dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
++		memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
++	}
++
++	dstate->copy = 1;
++
++	return 1;
++}
++
++
++const EVP_MD cryptodev_sha1 = {
++	NID_sha1,
++	NID_undef, 
++	SHA_DIGEST_LENGTH, 
++	EVP_MD_FLAG_ONESHOT,
++	cryptodev_digest_init,
++	cryptodev_digest_update,
++	cryptodev_digest_final,
++	cryptodev_digest_copy,
++	cryptodev_digest_cleanup,
++	EVP_PKEY_NULL_method,
++	SHA_CBLOCK,
++	sizeof(struct dev_crypto_state),
++};
++
++const EVP_MD cryptodev_md5 = {
++	NID_md5,
++	NID_undef, 
++	16 /* MD5_DIGEST_LENGTH */, 
++	EVP_MD_FLAG_ONESHOT,
++	cryptodev_digest_init,
++	cryptodev_digest_update,
++	cryptodev_digest_final,
++	cryptodev_digest_copy,
++	cryptodev_digest_cleanup,
++	EVP_PKEY_NULL_method,
++	64 /* MD5_CBLOCK */,
++	sizeof(struct dev_crypto_state),
++};
++
++#endif /* USE_CRYPTODEV_DIGESTS */
++
++
+ static int
+ cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
+     const int **nids, int nid)
+@@ -606,10 +883,15 @@
+ 		return (cryptodev_usable_digests(nids));
+ 
+ 	switch (nid) {
++#ifdef USE_CRYPTODEV_DIGESTS
+ 	case NID_md5:
+-		*digest = NULL; /* need to make a clean md5 critter */
++		*digest = &cryptodev_md5; 
+ 		break;
++	case NID_sha1:
++		*digest = &cryptodev_sha1;
++ 		break;
+ 	default:
++#endif /* USE_CRYPTODEV_DIGESTS */
+ 		*digest = NULL;
+ 		break;
+ 	}
+@@ -625,7 +907,7 @@
+ bn2crparam(const BIGNUM *a, struct crparam *crp)
+ {
+ 	int i, j, k;
+-	ssize_t words, bytes, bits;
++	ssize_t bytes, bits;
+ 	u_char *b;
+ 
+ 	crp->crp_p = NULL;
+@@ -637,6 +919,7 @@
+ 	b = malloc(bytes);
+ 	if (b == NULL)
+ 		return (1);
++	memset(b, 0, bytes);
+ 
+ 	crp->crp_p = b;
+ 	crp->crp_nbits = bits;
+@@ -681,7 +964,7 @@
+ {
+ 	int i;
+ 
+-	for (i = 0; i <= kop->crk_iparams + kop->crk_oparams; i++) {
++	for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) {
+ 		if (kop->crk_param[i].crp_p)
+ 			free(kop->crk_param[i].crp_p);
+ 		kop->crk_param[i].crp_p = NULL;
+@@ -756,12 +1039,10 @@
+ }
+ 
+ static int
+-cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
++cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+ {
+ 	int r;
+-	BN_CTX *ctx;
+-
+-	ctx = BN_CTX_new();
++	ctx = BN_CTX_new(); /* not sure why we reallocate this. DM */
+ 	r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL);
+ 	BN_CTX_free(ctx);
+ 	return (r);
+diff -urN openssl-0.9.8e.old/crypto/engine/engine.h openssl-0.9.8e/crypto/engine/engine.h
+--- openssl-0.9.8e.old/crypto/engine/engine.h	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/engine/engine.h	2008-02-26 10:31:12.000000000 -0500
+@@ -688,7 +688,7 @@
+  * values. */
+ void *ENGINE_get_static_state(void);
+ 
+-#if defined(__OpenBSD__) || defined(__FreeBSD__)
++#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+ void ENGINE_setup_bsd_cryptodev(void);
+ #endif
+ 
+diff -urN openssl-0.9.8e.old/crypto/engine/eng_table.c openssl-0.9.8e/crypto/engine/eng_table.c
+--- openssl-0.9.8e.old/crypto/engine/eng_table.c	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/engine/eng_table.c	2008-02-26 10:31:12.000000000 -0500
+@@ -151,8 +151,6 @@
+ 		/* if 'setdefault', this ENGINE goes to the head of the list */
+ 		if(!sk_ENGINE_push(fnd->sk, e))
+ 			goto end;
+-		/* "touch" this ENGINE_PILE */
+-		fnd->uptodate = 1;
+ 		if(setdefault)
+ 			{
+ 			if(!engine_unlocked_init(e))
+@@ -164,6 +162,8 @@
+ 			if(fnd->funct)
+ 				engine_unlocked_finish(fnd->funct, 0);
+ 			fnd->funct = e;
++			/* "touch" this ENGINE_PILE */
++			fnd->uptodate = 1;
+ 			}
+ 		nids++;
+ 		}
+@@ -179,13 +179,13 @@
+ 	while((n = sk_ENGINE_find(pile->sk, e)) >= 0)
+ 		{
+ 		sk_ENGINE_delete(pile->sk, n);
+-		/* "touch" this ENGINE_CIPHER */
+-		pile->uptodate = 1;
+ 		}
+ 	if(pile->funct == e)
+ 		{
+ 		engine_unlocked_finish(e, 0);
+ 		pile->funct = NULL;
++		/* "touch" this ENGINE_CIPHER */
++		pile->uptodate = 0;
+ 		}
+ 	}
+ static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb,ENGINE_PILE *,ENGINE *)
+diff -urN openssl-0.9.8e.old/crypto/evp/c_all.c openssl-0.9.8e/crypto/evp/c_all.c
+--- openssl-0.9.8e.old/crypto/evp/c_all.c	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/evp/c_all.c	2008-02-26 10:31:12.000000000 -0500
+@@ -83,7 +83,7 @@
+ 	OpenSSL_add_all_ciphers();
+ 	OpenSSL_add_all_digests();
+ #ifndef OPENSSL_NO_ENGINE
+-# if defined(__OpenBSD__) || defined(__FreeBSD__)
++# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+ 	ENGINE_setup_bsd_cryptodev();
+ # endif
+ #endif
+diff -urN openssl-0.9.8e.old/crypto/evp/c_alld.c openssl-0.9.8e/crypto/evp/c_alld.c
+--- openssl-0.9.8e.old/crypto/evp/c_alld.c	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/crypto/evp/c_alld.c	2008-02-26 10:31:12.000000000 -0500
+@@ -81,7 +81,7 @@
+ 	EVP_add_digest(EVP_dss());
+ #endif
+ #endif
+-#ifndef OPENSSL_NO_SHA
++#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
+ 	EVP_add_digest(EVP_sha1());
+ 	EVP_add_digest_alias(SN_sha1,"ssl3-sha1");
+ 	EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA);
+diff -urN openssl-0.9.8e.old/engines/Makefile openssl-0.9.8e/engines/Makefile
+--- openssl-0.9.8e.old/engines/Makefile	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/engines/Makefile	2008-02-26 10:31:12.000000000 -0500
+@@ -93,6 +93,7 @@
+ 			( echo installing $$l; \
+ 			  if [ "$(PLATFORM)" != "Cygwin" ]; then \
+ 				case "$(CFLAGS)" in \
++				*OPENSSL_NO_HW*)	continue;;	\
+ 				*DSO_DLFCN*)	sfx="so";;	\
+ 				*DSO_DL*)	sfx="sl";;	\
+ 				*)		sfx="bad";;	\
+diff -urN openssl-0.9.8e.old/INSTALL openssl-0.9.8e/INSTALL
+--- openssl-0.9.8e.old/INSTALL	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/INSTALL	2008-02-26 10:31:12.000000000 -0500
+@@ -103,6 +103,12 @@
+                 define preprocessor symbols, specify additional libraries,
+                 library directories or other compiler options.
+ 
++  --with-cryptodev Enabled the BSD cryptodev engine even if we are not using
++		BSD.  Useful if you are running ocf-linux or something
++		similar.  Once enabled you can also enable the use of
++		cryptodev digests,  with is usually slower unless you have
++		large amounts data.  Use --with-cryptodev-digests to force
++		it.
+ 
+  Installation in Detail
+  ----------------------
+diff -urN openssl-0.9.8e.old/Makefile.org openssl-0.9.8e/Makefile.org
+--- openssl-0.9.8e.old/Makefile.org	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/Makefile.org	2008-02-26 10:31:12.000000000 -0500
+@@ -367,7 +367,7 @@
+ 
+ links:
+ 	@$(PERL) $(TOP)/util/mkdir-p.pl include/openssl
+-	@$(PERL) $(TOP)/util/mklink.pl include/openssl $(EXHEADER)
++	@$(PERL) $(TOP)/util/mklink.pl include/openssl $(HEADER) $(EXHEADER)
+ 	@set -e; target=links; $(RECURSIVE_BUILD_CMD)
+ 
+ gentests:
+diff -urN openssl-0.9.8e.old/Makefile.shared openssl-0.9.8e/Makefile.shared
+--- openssl-0.9.8e.old/Makefile.shared	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/Makefile.shared	2008-02-26 10:31:12.000000000 -0500
+@@ -6,13 +6,13 @@
+ # properly
+ 
+ # CC contains the current compiler.  This one MUST be defined
+-CC=cc
+-CFLAGS=$(CFLAG)
++CC?=cc
++CFLAGS?=$(CFLAG)
+ # LDFLAGS contains flags to be used when temporary object files (when building
+ # shared libraries) are created, or when an application is linked.
+ # SHARED_LDFLAGS contains flags to be used when the shared library is created.
+-LDFLAGS=
+-SHARED_LDFLAGS=
++LDFLAGS?=
++SHARED_LDFLAGS?=
+ 
+ # LIBNAME contains just the name of the library, without prefix ("lib"
+ # on Unix, "cyg" for certain forms under Cygwin...) or suffix (.a, .so,
+diff -urN openssl-0.9.8e.old/util/domd openssl-0.9.8e/util/domd
+--- openssl-0.9.8e.old/util/domd	2008-02-26 10:30:37.000000000 -0500
++++ openssl-0.9.8e/util/domd	2008-02-26 10:34:04.000000000 -0500
+@@ -23,13 +23,17 @@
+     done
+     sed -e '/^# DO NOT DELETE.*/,$d' < Makefile > Makefile.tmp
+     echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' >> Makefile.tmp
+-    ${MAKEDEPEND} -D OPENSSL_DOING_MAKEDEPEND -M $args >> Makefile.tmp
++    ${MAKEDEPEND} -D OPENSSL_DOING_MAKEDEPEND -M $args >> Makefile.tmp && 
+     ${PERL} $TOP/util/clean-depend.pl < Makefile.tmp > Makefile.new
++      RC=$?
+     rm -f Makefile.tmp
+ else
+-    ${MAKEDEPEND} -D OPENSSL_DOING_MAKEDEPEND $@
++    ${MAKEDEPEND} -D OPENSSL_DOING_MAKEDEPEND $@ &&
+     ${PERL} $TOP/util/clean-depend.pl < Makefile > Makefile.new
++      RC=$?
+ fi
+ mv Makefile.new Makefile
+ # unfake the presence of Kerberos
+ rm $TOP/krb5.h
++
++exit $RC
+diff -urN --exclude=.svn openssl-0.9.8e.old/crypto/engine/eng_cryptodev.c openssl-0.9.8e/crypto/engine/eng_cryptodev.c
+--- openssl-0.9.8e.old/crypto/engine/eng_cryptodev.c	2008-02-27 20:05:09.000000000 -0500
++++ openssl-0.9.8e/crypto/engine/eng_cryptodev.c	2008-02-27 20:05:27.000000000 -0500
+@@ -54,7 +54,7 @@
+ #else 
+  
+ #include <sys/types.h>
+-#include <crypto/cryptodev.h>
++#include <cryptodev.h>
+ #include <sys/ioctl.h>
+ #include <errno.h>
+ #include <stdio.h>
diff -Nur kamikaze_7.09.orig/package/openvpn/files/openvpn.default kamikaze_7.09/package/openvpn/files/openvpn.default
--- kamikaze_7.09.orig/package/openvpn/files/openvpn.default	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/openvpn/files/openvpn.default	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,2 @@
+CONFIG="/etc/openvpn/server.conf"
+OPTIONS="--config $CONFIG"
diff -Nur kamikaze_7.09.orig/package/openvpn/files/openvpn.init kamikaze_7.09/package/openvpn/files/openvpn.init
--- kamikaze_7.09.orig/package/openvpn/files/openvpn.init	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/openvpn/files/openvpn.init	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+
+START=70
+BIN=openvpn
+DEFAULT=/etc/default/$BIN
+RUN_D=/var/run
+PID_F=$RUN_D/$BIN.pid
+
+start() {
+	[ -f $DEFAULT ] && . $DEFAULT
+	mkdir -p $RUN_D
+	$BIN --writepid $RUN_D/$BIN.pid --daemon $OPTIONS
+}
+
+stop() {
+	[ -f $PID_F ] && kill $(cat $PID_F)
+}
diff -Nur kamikaze_7.09.orig/package/openvpn/Makefile kamikaze_7.09/package/openvpn/Makefile
--- kamikaze_7.09.orig/package/openvpn/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/openvpn/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 9974 2007-12-28 13:31:04Z nix $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openvpn
+PKG_VERSION:=2.0.9
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://openvpn.net/release @SF/openvpn
+PKG_MD5SUM:=60745008b90b7dbe25fe8337c550fec6
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/openvpn
+  SECTION:=net
+  CATEGORY:=Network
+  DEPENDS:=+kmod-tun +libopenssl
+  TITLE:=Open source VPN solution using SSL
+  URL:=http://openvpn.net
+  SUBMENU:=VPN
+endef
+
+define Package/openvpn/description
+	 Open source VPN solution using SSL
+endef
+
+define Package/openvpn-easy-rsa
+  $(call Package/openvpn)
+  DEPENDS:=openvpn +openssl-util
+  TITLE:=Simple shell scripts to manage a Certificate Authority
+endef
+
+define Build/Configure
+	$(call Build/Configure/Default, \
+		--disable-pthread \
+		--disable-debug \
+		--disable-plugins \
+		--enable-management \
+		--disable-socks \
+                --disable-lzo \
+		--enable-password-save \
+	)
+endef
+
+define Build/Compile	
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		DESTDIR="$(PKG_INSTALL_DIR)" \
+		all install
+endef
+
+define Package/openvpn/install	
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/openvpn $(1)/usr/sbin/
+	$(INSTALL_DIR) $(1)/etc/init.d/
+	$(INSTALL_BIN) files/$(PKG_NAME).init $(1)/etc/init.d/$(PKG_NAME)
+	$(INSTALL_DIR) $(1)/etc/default
+	$(INSTALL_BIN) files/$(PKG_NAME).default $(1)/etc/default/$(PKG_NAME)
+endef
+
+define Package/openvpn-easy-rsa/install	
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_BUILD_DIR)/easy-rsa/2.0/{build-*,clean-all,inherit-inter,list-crl,pkitool,revoke-full,sign-req,whichopensslcnf} $(1)/usr/sbin/
+	$(INSTALL_DIR) $(1)/etc/easy-rsa
+	install -m 0644 $(PKG_BUILD_DIR)/easy-rsa/2.0/openssl.cnf $(1)/etc/easy-rsa/openssl.cnf
+	install -m 0644 $(PKG_BUILD_DIR)/easy-rsa/2.0/vars $(1)/etc/easy-rsa/vars
+endef
+
+$(eval $(call BuildPackage,openvpn))
+$(eval $(call BuildPackage,openvpn-easy-rsa))
diff -Nur kamikaze_7.09.orig/package/openvpn/patches/001-easy_rsa.patch kamikaze_7.09/package/openvpn/patches/001-easy_rsa.patch
--- kamikaze_7.09.orig/package/openvpn/patches/001-easy_rsa.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/openvpn/patches/001-easy_rsa.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,249 @@
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-ca openvpn-2.0.7/easy-rsa/2.0/build-ca
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-ca	2005-11-02 19:42:38.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-ca	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ #
+ # Build a root certificate
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-dh openvpn-2.0.7/easy-rsa/2.0/build-dh
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-dh	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-dh	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,6 @@
+-#!/bin/bash
++#!/bin/sh
++
++. /etc/easy-rsa/vars
+ 
+ # Build Diffie-Hellman parameters for the server side
+ # of an SSL/TLS connection.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-inter openvpn-2.0.7/easy-rsa/2.0/build-inter
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-inter	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-inter	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Make an intermediate CA certificate/private key pair using a locally generated
+ # root certificate.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-key openvpn-2.0.7/easy-rsa/2.0/build-key
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-key	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-key	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Make a certificate/private key pair using a locally generated
+ # root certificate.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-key-pass openvpn-2.0.7/easy-rsa/2.0/build-key-pass
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-key-pass	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-key-pass	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Similar to build-key, but protect the private key
+ # with a password.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-key-pkcs12 openvpn-2.0.7/easy-rsa/2.0/build-key-pkcs12
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-key-pkcs12	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-key-pkcs12	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Make a certificate/private key pair using a locally generated
+ # root certificate and convert it to a PKCS #12 file including the
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-key-server openvpn-2.0.7/easy-rsa/2.0/build-key-server
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-key-server	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-key-server	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Make a certificate/private key pair using a locally generated
+ # root certificate.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-req openvpn-2.0.7/easy-rsa/2.0/build-req
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-req	2005-11-02 19:42:38.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-req	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Build a certificate signing request and private key.  Use this
+ # when your root certificate and key is not available locally.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/build-req-pass openvpn-2.0.7/easy-rsa/2.0/build-req-pass
+--- openvpn-2.0.7.orig/easy-rsa/2.0/build-req-pass	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/build-req-pass	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Like build-req, but protect your private key
+ # with a password.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/clean-all openvpn-2.0.7/easy-rsa/2.0/clean-all
+--- openvpn-2.0.7.orig/easy-rsa/2.0/clean-all	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/clean-all	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,6 @@
+-#!/bin/bash
++#!/bin/sh
++
++. /etc/easy-rsa/vars
+ 
+ # Initialize the $KEY_DIR directory.
+ # Note that this script does a
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/inherit-inter openvpn-2.0.7/easy-rsa/2.0/inherit-inter
+--- openvpn-2.0.7.orig/easy-rsa/2.0/inherit-inter	2005-11-02 19:42:38.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/inherit-inter	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,6 @@
+-#!/bin/bash
++#!/bin/sh
++
++. /etc/easy-rsa/vars
+ 
+ # Build a new PKI which is rooted on an intermediate certificate generated
+ # by ./build-inter or ./pkitool --inter from a parent PKI.  The new PKI should
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/list-crl openvpn-2.0.7/easy-rsa/2.0/list-crl
+--- openvpn-2.0.7.orig/easy-rsa/2.0/list-crl	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/list-crl	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,6 @@
+-#!/bin/bash
++#!/bin/sh
++
++. /etc/easy-rsa/vars
+ 
+ # list revoked certificates
+ 
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/pkitool openvpn-2.0.7/easy-rsa/2.0/pkitool
+--- openvpn-2.0.7.orig/easy-rsa/2.0/pkitool	2005-11-02 19:42:38.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/pkitool	2006-05-09 17:47:40.000000000 +0200
+@@ -1,5 +1,7 @@
+ #!/bin/sh
+ 
++. /etc/easy-rsa/vars
++
+ #  OpenVPN -- An application to securely tunnel IP networks
+ #             over a single TCP/UDP port, with support for SSL/TLS-based
+ #             session authentication and key exchange,
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/revoke-full openvpn-2.0.7/easy-rsa/2.0/revoke-full
+--- openvpn-2.0.7.orig/easy-rsa/2.0/revoke-full	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/revoke-full	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,6 @@
+-#!/bin/bash
++#!/bin/sh
++
++. /etc/easy-rsa/vars
+ 
+ # revoke a certificate, regenerate CRL,
+ # and verify revocation
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/sign-req openvpn-2.0.7/easy-rsa/2.0/sign-req
+--- openvpn-2.0.7.orig/easy-rsa/2.0/sign-req	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/sign-req	2006-05-09 17:47:40.000000000 +0200
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Sign a certificate signing request (a .csr file)
+ # with a local root certificate and key.
+diff -ur openvpn-2.0.7.orig/easy-rsa/2.0/vars openvpn-2.0.7/easy-rsa/2.0/vars
+--- openvpn-2.0.7.orig/easy-rsa/2.0/vars	2005-11-02 19:42:39.000000000 +0100
++++ openvpn-2.0.7/easy-rsa/2.0/vars	2006-05-09 17:47:40.000000000 +0200
+@@ -12,7 +12,7 @@
+ # This variable should point to
+ # the top level of the easy-rsa
+ # tree.
+-export EASY_RSA="`pwd`"
++export EASY_RSA="/etc/easy-rsa"
+ 
+ #
+ # This variable should point to
+@@ -26,7 +26,7 @@
+ # This variable should point to
+ # the openssl.cnf file included
+ # with easy-rsa.
+-export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
++export KEY_CONFIG=`/usr/sbin/whichopensslcnf $EASY_RSA`
+ 
+ # Edit this variable to point to
+ # your soon-to-be-created key
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-ca openvpn-2.0.9/easy-rsa/2.0/build-ca
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-ca	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-ca	2007-06-18 01:21:07.000000000 +0200
+@@ -5,4 +5,4 @@
+ #
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --initca $*
++"/usr/sbin/pkitool" --interact --initca $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-inter openvpn-2.0.9/easy-rsa/2.0/build-inter
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-inter	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-inter	2007-06-18 01:21:19.000000000 +0200
+@@ -4,4 +4,4 @@
+ # root certificate.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --inter $*
++"/usr/sbin/pkitool" --interact --inter $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-key openvpn-2.0.9/easy-rsa/2.0/build-key
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-key	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-key	2007-06-18 01:21:32.000000000 +0200
+@@ -4,4 +4,4 @@
+ # root certificate.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact $*
++"/usr/sbin/pkitool" --interact $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-key-pass openvpn-2.0.9/easy-rsa/2.0/build-key-pass
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-key-pass	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-key-pass	2007-06-18 01:21:45.000000000 +0200
+@@ -4,4 +4,4 @@
+ # with a password.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --pass $*
++"/usr/sbin/pkitool" --interact --pass $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-key-pkcs12 openvpn-2.0.9/easy-rsa/2.0/build-key-pkcs12
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-key-pkcs12	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-key-pkcs12	2007-06-18 01:21:57.000000000 +0200
+@@ -5,4 +5,4 @@
+ # the CA certificate as well.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --pkcs12 $*
++"/usr/sbin/pkitool" --interact --pkcs12 $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-key-server openvpn-2.0.9/easy-rsa/2.0/build-key-server
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-key-server	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-key-server	2007-06-18 01:22:09.000000000 +0200
+@@ -7,4 +7,4 @@
+ # extension in the openssl.cnf file.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --server $*
++"/usr/sbin/pkitool" --interact --server $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-req openvpn-2.0.9/easy-rsa/2.0/build-req
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-req	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-req	2007-06-18 01:22:27.000000000 +0200
+@@ -4,4 +4,4 @@
+ # when your root certificate and key is not available locally.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --csr $*
++"/usr/sbin/pkitool" --interact --csr $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/build-req-pass openvpn-2.0.9/easy-rsa/2.0/build-req-pass
+--- openvpn-2.0.9.orig/easy-rsa/2.0/build-req-pass	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/build-req-pass	2007-06-18 01:22:38.000000000 +0200
+@@ -4,4 +4,4 @@
+ # with a password.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --csr --pass $*
++"/usr/sbin/pkitool" --interact --csr --pass $*
+diff -urN openvpn-2.0.9.orig/easy-rsa/2.0/sign-req openvpn-2.0.9/easy-rsa/2.0/sign-req
+--- openvpn-2.0.9.orig/easy-rsa/2.0/sign-req	2007-06-18 01:20:36.000000000 +0200
++++ openvpn-2.0.9/easy-rsa/2.0/sign-req	2007-06-18 01:22:53.000000000 +0200
+@@ -4,4 +4,4 @@
+ # with a local root certificate and key.
+ 
+ export EASY_RSA="${EASY_RSA:-.}"
+-"$EASY_RSA/pkitool" --interact --sign $*
++"/usr/sbin/pkitool" --interact --sign $*
diff -Nur kamikaze_7.09.orig/package/screen/Makefile kamikaze_7.09/package/screen/Makefile
--- kamikaze_7.09.orig/package/screen/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/screen/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 9349 2007-10-18 18:46:37Z blogic $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=screen
+PKG_VERSION:=4.0.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://ftp.uni-erlangen.de/pub/utilities/screen \
+	@GNU/screen
+PKG_MD5SUM:=8506fd205028a96c741e4037de6e3c42
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/screen
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libncurses
+  TITLE:=Full-screen terminal window manager
+  URL:=http://www.gnu.org/software/screen/
+endef
+
+define Package/screen/description
+	Screen is a full-screen window manager that multiplexes a physical
+	terminal between several processes, typically interactive shells.
+endef
+
+define Build/Configure
+	$(call Build/Configure/Default,,\
+		LIBS="-lcrypt" \
+	)
+endef
+
+define Package/screen/install	
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/screen $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,screen))
diff -Nur kamikaze_7.09.orig/package/screen/patches/100-cross_compile_fix.patch kamikaze_7.09/package/screen/patches/100-cross_compile_fix.patch
--- kamikaze_7.09.orig/package/screen/patches/100-cross_compile_fix.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/screen/patches/100-cross_compile_fix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,530 @@
+Binary files screen-4.0.2.old/.configure.swp and screen-4.0.2.dev/.configure.swp differ
+diff -urN screen-4.0.2.old/configure screen-4.0.2.dev/configure
+--- screen-4.0.2.old/configure	2003-12-05 14:46:53.000000000 +0100
++++ screen-4.0.2.dev/configure	2005-05-05 12:13:03.000000000 +0200
+@@ -124,7 +124,7 @@
+   fi
+   if test ! -f "$as_myself"; then
+     { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+-   { (exit 1); exit 1; }; }
++    }
+   fi
+   case $CONFIG_SHELL in
+   '')
+@@ -174,7 +174,7 @@
+     ' >$as_me.lineno &&
+   chmod +x $as_me.lineno ||
+     { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+-   { (exit 1); exit 1; }; }
++    }
+ 
+   # Don't try to exec as it changes $[0], causing all sort of problems
+   # (the dirname of $[0] is not the place where we might find the
+@@ -397,7 +397,7 @@
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+       { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+-   { (exit 1); exit 1; }; }
++    }
+     ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+     eval "enable_$ac_feature=no" ;;
+ 
+@@ -406,7 +406,7 @@
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+       { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+-   { (exit 1); exit 1; }; }
++    }
+     ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+     case $ac_option in
+       *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+@@ -588,7 +588,7 @@
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+       { echo "$as_me: error: invalid package name: $ac_package" >&2
+-   { (exit 1); exit 1; }; }
++    }
+     ac_package=`echo $ac_package| sed 's/-/_/g'`
+     case $ac_option in
+       *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+@@ -601,7 +601,7 @@
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+       { echo "$as_me: error: invalid package name: $ac_package" >&2
+-   { (exit 1); exit 1; }; }
++    }
+     ac_package=`echo $ac_package | sed 's/-/_/g'`
+     eval "with_$ac_package=no" ;;
+ 
+@@ -625,7 +625,7 @@
+ 
+   -*) { echo "$as_me: error: unrecognized option: $ac_option
+ Try \`$0 --help' for more information." >&2
+-   { (exit 1); exit 1; }; }
++    }
+     ;;
+ 
+   *=*)
+@@ -633,7 +633,7 @@
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+       { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+-   { (exit 1); exit 1; }; }
++    }
+     ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+     eval "$ac_envvar='$ac_optarg'"
+     export $ac_envvar ;;
+@@ -652,7 +652,7 @@
+ if test -n "$ac_prev"; then
+   ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+   { echo "$as_me: error: missing argument to $ac_option" >&2
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ 
+ # Be sure to have absolute paths.
+@@ -662,7 +662,7 @@
+   case $ac_val in
+     [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+     *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+-   { (exit 1); exit 1; }; };;
++    };;
+   esac
+ done
+ 
+@@ -674,7 +674,7 @@
+   case $ac_val in
+     [\\/$]* | ?:[\\/]* ) ;;
+     *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+-   { (exit 1); exit 1; }; };;
++    };;
+   esac
+ done
+ 
+@@ -728,15 +728,15 @@
+ if test ! -r $srcdir/$ac_unique_file; then
+   if test "$ac_srcdir_defaulted" = yes; then
+     { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+-   { (exit 1); exit 1; }; }
++    }
+   else
+     { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+-   { (exit 1); exit 1; }; }
++    }
+   fi
+ fi
+ (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+   { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+-   { (exit 1); exit 1; }; }
++    }
+ srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ ac_env_build_alias_set=${build_alias+set}
+ ac_env_build_alias_value=$build_alias
+@@ -1243,7 +1243,7 @@
+ echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+   { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+ echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ 
+ ac_ext=c
+@@ -1734,7 +1734,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: no acceptable C compiler found in \$PATH
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ 
+ # Provide some information about the compiler.
+ echo "$as_me:$LINENO:" \
+@@ -1856,7 +1856,7 @@
+ echo "$as_me: error: cannot run C compiled programs.
+ If you meant to cross compile, use \`--host'.
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+     fi
+   fi
+ fi
+@@ -1898,7 +1898,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ 
+ rm -f conftest$ac_cv_exeext
+@@ -1950,7 +1950,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot compute suffix of object files: cannot compile
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ 
+ rm -f conftest.$ac_cv_objext conftest.$ac_ext
+@@ -2514,7 +2514,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ 
+ ac_ext=c
+@@ -2704,7 +2704,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -2753,7 +2753,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++  }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -2790,7 +2790,7 @@
+ 
+ { { echo "$as_me:$LINENO: error: Can't run the compiler - sorry" >&5
+ echo "$as_me: error: Can't run the compiler - sorry" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+ fi
+@@ -2800,7 +2800,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++  }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -2830,7 +2830,7 @@
+   (exit $ac_status); }; }; then
+   { { echo "$as_me:$LINENO: error: Your compiler does not set the exit status - sorry" >&5
+ echo "$as_me: error: Your compiler does not set the exit status - sorry" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   echo "$as_me: program exited with status $ac_status" >&5
+ echo "$as_me: failed program was:" >&5
+@@ -2900,7 +2900,7 @@
+ if test -z "$ac_aux_dir"; then
+   { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+ echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+@@ -4149,7 +4149,7 @@
+ 
+ { { echo "$as_me:$LINENO: error: !!! no select - no screen" >&5
+ echo "$as_me: error: !!! no select - no screen" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ 
+@@ -4163,7 +4163,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++  }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -4272,7 +4272,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++  }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -4365,7 +4365,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++  }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -4460,7 +4460,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++  }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -4562,7 +4562,7 @@
+ else
+   { { echo "$as_me:$LINENO: error: you have neither usable sockets nor usable pipes -> no screen" >&5
+ echo "$as_me: error: you have neither usable sockets nor usable pipes -> no screen" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ 
+ 
+@@ -4573,7 +4573,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -4898,7 +4898,7 @@
+ 
+ { { echo "$as_me:$LINENO: error: !!! no tgetent - no screen" >&5
+ echo "$as_me: error: !!! no tgetent - no screen" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ fi
+@@ -4915,7 +4915,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -5359,7 +5356,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -6206,7 +6203,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -6482,7 +6479,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -7004,7 +7001,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -7056,7 +7053,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -7110,7 +7107,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -7951,7 +7948,7 @@
+ See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run test program while cross compiling
+ See \`config.log' for more details." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -7982,7 +7979,7 @@
+ ( exit $ac_status )
+ { { echo "$as_me:$LINENO: error: Can't run the compiler - internal error. Sorry." >&5
+ echo "$as_me: error: Can't run the compiler - internal error. Sorry." >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ fi
+ rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+ fi
+@@ -8251,7 +8248,7 @@
+   if test ! -f "$as_myself"; then
+     { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+ echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+   fi
+   case $CONFIG_SHELL in
+   '')
+@@ -8302,7 +8299,7 @@
+   chmod +x $as_me.lineno ||
+     { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+ echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+ 
+   # Don't try to exec as it changes $[0], causing all sort of problems
+   # (the dirname of $[0] is not the place where we might find the
+@@ -8494,7 +8491,7 @@
+ Try \`$0 --help' for more information." >&5
+ echo "$as_me: error: ambiguous option: $1
+ Try \`$0 --help' for more information." >&2;}
+-   { (exit 1); exit 1; }; };;
++    };;
+   --help | --hel | -h )
+     echo "$ac_cs_usage"; exit 0 ;;
+   --debug | --d* | -d )
+@@ -8516,7 +8513,7 @@
+ Try \`$0 --help' for more information." >&5
+ echo "$as_me: error: unrecognized option: $1
+ Try \`$0 --help' for more information." >&2;}
+-   { (exit 1); exit 1; }; } ;;
++    } ;;
+ 
+   *) ac_config_targets="$ac_config_targets $1" ;;
+ 
+@@ -8555,7 +8552,7 @@
+   "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+   *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+ echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+-   { (exit 1); exit 1; }; };;
++    };;
+   esac
+ done
+ 
+@@ -8750,7 +8747,7 @@
+     test ! -n "$as_dirs" || mkdir $as_dirs
+   fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+ echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+-   { (exit 1); exit 1; }; }; }
++    }; }
+ 
+   ac_builddir=.
+ 
+@@ -8816,7 +8813,7 @@
+          # Absolute (can't be DOS-style, as IFS=:)
+          test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+          echo $f;;
+       *) # Relative
+          if test -f "$f"; then
+@@ -8829,7 +8826,7 @@
+            # /dev/null tree
+            { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+          fi;;
+       esac
+     done` || { (exit 1); exit 1; }
+@@ -8907,7 +8904,7 @@
+          # Absolute (can't be DOS-style, as IFS=:)
+          test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+          echo $f;;
+       *) # Relative
+          if test -f "$f"; then
+@@ -8920,7 +8917,7 @@
+            # /dev/null tree
+            { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+ echo "$as_me: error: cannot find input file: $f" >&2;}
+-   { (exit 1); exit 1; }; }
++    }
+          fi;;
+       esac
+     done` || { (exit 1); exit 1; }
+@@ -9073,7 +9070,7 @@
+     test ! -n "$as_dirs" || mkdir $as_dirs
+   fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+ echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+-   { (exit 1); exit 1; }; }; }
++    }; }
+ 
+       rm -f $ac_file
+       mv $tmp/config.h $ac_file
+diff -urN screen-4.0.2.old/pty.c screen-4.0.2.dev/pty.c
+--- screen-4.0.2.old/pty.c	2003-09-08 16:26:18.000000000 +0200
++++ screen-4.0.2.dev/pty.c	2005-05-05 12:32:20.000000000 +0200
+@@ -34,9 +34,9 @@
+ #endif
+ 
+ /* for solaris 2.1, Unixware (SVR4.2) and possibly others */
+-#ifdef HAVE_SVR4_PTYS
+-# include <sys/stropts.h>
+-#endif
++//#ifdef HAVE_SVR4_PTYS
++//# include <sys/stropts.h>
++//#endif
+ 
+ #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL)
+ # include <sys/ttold.h>
+--- screen-4.0.2/configure.old	2005-05-24 18:49:30.000000000 +0200
++++ screen-4.0.2/configure	2005-05-24 18:49:54.000000000 +0200
+@@ -6598,8 +6598,6 @@
+ LIBS="$oldlibs"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+-test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec"
+-test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow"
+ oldlibs="$LIBS"
+ LIBS="$LIBS -lsun"
+ { echo "$as_me:$LINENO: checking IRIX sun library..." >&5
+diff -ur screen.old/sched.h screen.dev/sched.h
+--- screen.old/sched.h	2002-01-08 16:42:43.000000000 +0100
++++ screen.dev/sched.h	2007-03-02 17:03:48.475830776 +0100
+@@ -22,6 +22,11 @@
+  * $Id: 100-cross_compile_fix.patch 6458 2007-03-02 16:12:30Z nbd $ FAU
+  */
+ 
++#ifndef __SCHED_H
++#define __SCHED_H
++
++#include <sys/time.h>
++
+ struct event
+ {
+   struct event *next;
+@@ -41,3 +46,5 @@
+ #define EV_READ		1
+ #define EV_WRITE	2
+ #define EV_ALWAYS	3
++
++#endif
diff -Nur kamikaze_7.09.orig/package/tcpdump/Makefile kamikaze_7.09/package/tcpdump/Makefile
--- kamikaze_7.09.orig/package/tcpdump/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/tcpdump/Makefile	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,58 @@
+# 
+# Copyright (C) 2007 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 9695 2007-12-09 18:59:01Z nbd $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tcpdump
+PKG_VERSION:=3.9.8
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.tcpdump.org/release/ \
+	http://ftp.gwdg.de/pub/misc/tcpdump/ \
+	http://www.at.tcpdump.org/ \
+	http://www.br.tcpdump.org/
+PKG_MD5SUM:=c491a78c52fe73f1f7271aa5d8c6ab2e
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tcpdump
+  SECTION:=net
+  CATEGORY:=Network
+  DEPENDS:=+libpcap
+  TITLE:=Network monitoring and data acquisition tool
+  URL:=http://www.tcpdump.org/
+endef
+
+define Build/Configure
+	$(call Build/Configure/Default, \
+		--enable-ipv6 \
+		--without-crypto \
+		, \
+		BUILD_CC="$(TARGET_CC)" \
+		HOSTCC="$(HOSTCC)" \
+		td_cv_buggygetaddrinfo="no" \
+	)
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CCOPT="$(TARGET_CFLAGS)" INCLS="-I. -I$(STAGING_DIR)/usr/include" \
+		DESTDIR="$(PKG_INSTALL_DIR)" \
+		all install
+endef
+
+define Package/tcpdump/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tcpdump $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,tcpdump))
diff -Nur kamikaze_7.09.orig/package/tcpdump/patches/001-remove_pcap_debug.patch kamikaze_7.09/package/tcpdump/patches/001-remove_pcap_debug.patch
--- kamikaze_7.09.orig/package/tcpdump/patches/001-remove_pcap_debug.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/tcpdump/patches/001-remove_pcap_debug.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,24 @@
+diff -urN tcpdump-3.9.4.orig/tcpdump.c tcpdump-3.9.4/tcpdump.c
+--- tcpdump-3.9.4.orig/tcpdump.c	2005-08-23 12:29:41.000000000 +0200
++++ tcpdump-3.9.4/tcpdump.c	2006-02-05 17:52:37.000000000 +0100
+@@ -762,20 +762,6 @@
+ 				error("invalid data link type %s", gndo->ndo_dltname);
+ 			break;
+ 
+-#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)
+-		case 'Y':
+-			{
+-			/* Undocumented flag */
+-#ifdef HAVE_PCAP_DEBUG
+-			extern int pcap_debug;
+-			pcap_debug = 1;
+-#else
+-			extern int yydebug;
+-			yydebug = 1;
+-#endif
+-			}
+-			break;
+-#endif
+ 		case 'Z':
+ 			if (optarg) {
+ 				username = strdup(optarg);
diff -Nur kamikaze_7.09.orig/target/linux/generic-2.6/files/drivers/leds/leds-alix.c kamikaze_7.09/target/linux/generic-2.6/files/drivers/leds/leds-alix.c
--- kamikaze_7.09.orig/target/linux/generic-2.6/files/drivers/leds/leds-alix.c	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/target/linux/generic-2.6/files/drivers/leds/leds-alix.c	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,172 @@
+/*
+ * LEDs driver for PCEngines ALIX 2/3 series
+ *
+ * Copyright (C) 2007 Petr Leibman
+ *
+ * Based on leds-wrap.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+#define DRVNAME "alix-led"
+
+#define ALIX_LED1_PORT		(0x6100)
+#define ALIX_LED1_ON		(1<<22)
+#define ALIX_LED1_OFF		(1<<6)
+
+#define ALIX_LED2_PORT		(0x6180)
+#define ALIX_LED2_ON		(1<<25)
+#define ALIX_LED2_OFF		(1<<9)
+
+#define ALIX_LED3_PORT		(0x6180)
+#define ALIX_LED3_ON		(1<<27)
+#define ALIX_LED3_OFF		(1<<11)
+
+
+static struct platform_device *pdev;
+
+static void alix_led_set_1(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	if (value)
+		outl(ALIX_LED1_ON, ALIX_LED1_PORT);
+	else
+		outl(ALIX_LED1_OFF, ALIX_LED1_PORT);
+}
+
+static void alix_led_set_2(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	if (value)
+		outl(ALIX_LED2_ON, ALIX_LED2_PORT);
+	else
+		outl(ALIX_LED2_OFF, ALIX_LED2_PORT);
+}
+
+static void alix_led_set_3(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	if (value)
+		outl(ALIX_LED3_ON, ALIX_LED3_PORT);
+	else
+		outl(ALIX_LED3_OFF, ALIX_LED3_PORT);
+}
+
+static struct led_classdev alix_led_1 = {
+	.name		= "alix:1",
+	.brightness_set	= alix_led_set_1,
+};
+
+static struct led_classdev alix_led_2 = {
+	.name		= "alix:2",
+	.brightness_set	= alix_led_set_2,
+};
+
+static struct led_classdev alix_led_3 = {
+	.name		= "alix:3",
+	.brightness_set	= alix_led_set_3,
+};
+
+
+#ifdef CONFIG_PM
+static int alix_led_suspend(struct platform_device *dev,
+		pm_message_t state)
+{
+	led_classdev_suspend(&alix_led_1);
+	led_classdev_suspend(&alix_led_2);
+	led_classdev_suspend(&alix_led_3);
+	return 0;
+}
+
+static int alix_led_resume(struct platform_device *dev)
+{
+	led_classdev_resume(&alix_led_1);
+	led_classdev_resume(&alix_led_2);
+	led_classdev_resume(&alix_led_3);
+	return 0;
+}
+#else
+#define alix_led_suspend NULL
+#define alix_led_resume NULL
+#endif
+
+static int alix_led_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = led_classdev_register(&pdev->dev, &alix_led_1);
+	if (ret == 0)
+	{
+		ret = led_classdev_register(&pdev->dev, &alix_led_2);
+		if (ret >= 0)
+		{
+			ret = led_classdev_register(&pdev->dev, &alix_led_3);
+			if (ret < 0)
+				led_classdev_unregister(&alix_led_2);
+		}
+		if (ret < 0)
+			led_classdev_unregister(&alix_led_1);
+	}
+	return ret;
+}
+
+static int alix_led_remove(struct platform_device *pdev)
+{
+	led_classdev_unregister(&alix_led_1);
+	led_classdev_unregister(&alix_led_2);
+	led_classdev_unregister(&alix_led_3);
+	return 0;
+}
+
+static struct platform_driver alix_led_driver = {
+	.probe		= alix_led_probe,
+	.remove		= alix_led_remove,
+	.suspend	= alix_led_suspend,
+	.resume		= alix_led_resume,
+	.driver		= {
+		.name		= DRVNAME,
+		.owner		= THIS_MODULE,
+	},
+};
+
+static int __init alix_led_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&alix_led_driver);
+	if (ret < 0)
+		goto out;
+
+	pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		ret = PTR_ERR(pdev);
+		platform_driver_unregister(&alix_led_driver);
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+static void __exit alix_led_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&alix_led_driver);
+}
+
+module_init(alix_led_init);
+module_exit(alix_led_exit);
+
+MODULE_AUTHOR("Petr Leibman");
+MODULE_DESCRIPTION("PCEngines ALIX LED driver");
+MODULE_LICENSE("GPL");
+
diff -Nur kamikaze_7.09.orig/target/linux/generic-2.6/patches-2.6.22/401-led-alix.patch kamikaze_7.09/target/linux/generic-2.6/patches-2.6.22/401-led-alix.patch
--- kamikaze_7.09.orig/target/linux/generic-2.6/patches-2.6.22/401-led-alix.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/target/linux/generic-2.6/patches-2.6.22/401-led-alix.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,28 @@
+diff -Nur linux-2.6.22.1.orig/drivers/leds/Kconfig linux-2.6.22.1/drivers/leds/Kconfig
+--- linux-2.6.22.1.orig/drivers/leds/Kconfig	2006-10-12 12:43:44.000000000 -0400
++++ linux-2.6.22.1/drivers/leds/Kconfig	2006-10-31 02:36:22.000000000 -0400
+@@ -83,6 +83,12 @@
+ 	help
+ 	  This option enables support for the PCEngines WRAP programmable LEDs.
+ 
++config LEDS_ALIX
++	tristate "LED Support for the ALIX 2/3 boards"
++	depends on LEDS_CLASS
++	help
++	  This option enables support for the three LEDs on the PCEngines ALIX 2/3 boards.
++
+ config LEDS_H1940
+ 	tristate "LED Support for iPAQ H1940 device"
+ 	depends LEDS_CLASS && ARCH_H1940
+diff -Nur linux-2.6.22.1.orig/drivers/leds/Makefile linux-2.6.22.1/drivers/leds/Makefile
+--- linux-2.6.22.1.orig/drivers/leds/Makefile	2006-10-12 12:43:44.000000000 -0400
++++ linux-2.6.22.1/drivers/leds/Makefile	2006-10-31 02:36:17.000000000 -0400
+@@ -14,6 +14,7 @@
+ obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
+ obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
+ obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
++obj-$(CONFIG_LEDS_ALIX)			+= leds-alix.o
+ obj-$(CONFIG_LEDS_H1940)		+= leds-h1940.o
+ obj-$(CONFIG_LEDS_COBALT)		+= leds-cobalt.o
+ obj-$(CONFIG_LEDS_GPIO)			+= leds-gpio.o
+
diff -Nur kamikaze_7.09.orig/target/linux/generic-2.6/patches-2.6.22/410-linux_ocf_kernel.patch kamikaze_7.09/target/linux/generic-2.6/patches-2.6.22/410-linux_ocf_kernel.patch
--- kamikaze_7.09.orig/target/linux/generic-2.6/patches-2.6.22/410-linux_ocf_kernel.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/target/linux/generic-2.6/patches-2.6.22/410-linux_ocf_kernel.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,19412 @@
+diff -urN linux-2.6.23.16.old/crypto/Kconfig linux-2.6.23.16/crypto/Kconfig
+--- linux-2.6.23.16.old/crypto/Kconfig	2008-02-26 09:26:41.000000000 -0500
++++ linux-2.6.23.16/crypto/Kconfig	2008-02-26 09:29:13.000000000 -0500
+@@ -464,4 +464,6 @@
+ 
+ endif  # if CRYPTO
+ 
++source "crypto/ocf/Kconfig"
++
+ endmenu
+diff -urN linux-2.6.23.16.old/crypto/Makefile linux-2.6.23.16/crypto/Makefile
+--- linux-2.6.23.16.old/crypto/Makefile	2008-02-26 09:26:41.000000000 -0500
++++ linux-2.6.23.16/crypto/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -50,3 +50,5 @@
+ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
+ 
+ obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
++
++obj-$(CONFIG_OCF_OCF) += ocf/
+diff -urN linux-2.6.23.16.old/crypto/ocf/Config.in linux-2.6.23.16/crypto/ocf/Config.in
+--- linux-2.6.23.16.old/crypto/ocf/Config.in	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/Config.in	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,32 @@
++#############################################################################
++
++mainmenu_option next_comment
++comment 'OCF Configuration'
++tristate 'OCF (Open Cryptograhic Framework)' CONFIG_OCF_OCF
++dep_tristate '  enable fips RNG checks (fips check on RNG data before use)' \
++				CONFIG_OCF_FIPS $CONFIG_OCF_OCF
++dep_tristate '  enable harvesting entropy for /dev/random' \
++				CONFIG_OCF_RANDOMHARVEST $CONFIG_OCF_OCF
++dep_tristate '  cryptodev (user space support)' \
++				CONFIG_OCF_CRYPTODEV $CONFIG_OCF_OCF
++dep_tristate '  cryptosoft (software crypto engine)' \
++				CONFIG_OCF_CRYPTOSOFT $CONFIG_OCF_OCF
++dep_tristate '  safenet (HW crypto engine)' \
++				CONFIG_OCF_SAFE $CONFIG_OCF_OCF
++dep_tristate '  IXP4xx (HW crypto engine)' \
++				CONFIG_OCF_IXP4XX $CONFIG_OCF_OCF
++dep_mbool    '  Enable IXP4xx HW to perform SHA1 and MD5 hashing (very slow)' \
++				CONFIG_OCF_IXP4XX_SHA1_MD5 $CONFIG_OCF_IXP4XX
++dep_tristate '  hifn (HW crypto engine)' \
++				CONFIG_OCF_HIFN $CONFIG_OCF_OCF
++dep_tristate '  talitos (HW crypto engine)' \
++				CONFIG_OCF_TALITOS $CONFIG_OCF_OCF
++dep_tristate '  pasemi (HW crypto engine)' \
++				CONFIG_OCF_PASEMI $CONFIG_OCF_OCF
++dep_tristate '  ocfnull (does no crypto)' \
++				CONFIG_OCF_OCFNULL $CONFIG_OCF_OCF
++dep_tristate '  ocf-bench (HW crypto in-kernel benchmark)' \
++				CONFIG_OCF_BENCH $CONFIG_OCF_OCF
++endmenu
++
++#############################################################################
+diff -urN linux-2.6.23.16.old/crypto/ocf/criov.c linux-2.6.23.16/crypto/ocf/criov.c
+--- linux-2.6.23.16.old/crypto/ocf/criov.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/criov.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,215 @@
++/*      $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $	*/
++
++/*
++ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ * The license and original author are listed below.
++ *
++ * Copyright (c) 1999 Theo de Raadt
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *   derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++__FBSDID("$FreeBSD: src/sys/opencrypto/criov.c,v 1.5 2006/06/04 22:15:13 pjd Exp $");
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/uio.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <asm/io.h>
++
++#include <uio.h>
++#include <cryptodev.h>
++
++/*
++ * This macro is only for avoiding code duplication, as we need to skip
++ * given number of bytes in the same way in three functions below.
++ */
++#define	CUIO_SKIP()	do {						\
++	KASSERT(off >= 0, ("%s: off %d < 0", __func__, off));		\
++	KASSERT(len >= 0, ("%s: len %d < 0", __func__, len));		\
++	while (off > 0) {						\
++		KASSERT(iol >= 0, ("%s: empty in skip", __func__));	\
++		if (off < iov->iov_len)					\
++			break;						\
++		off -= iov->iov_len;					\
++		iol--;							\
++		iov++;							\
++	}								\
++} while (0)
++
++void
++cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
++{
++	struct iovec *iov = uio->uio_iov;
++	int iol = uio->uio_iovcnt;
++	unsigned count;
++
++	CUIO_SKIP();
++	while (len > 0) {
++		KASSERT(iol >= 0, ("%s: empty", __func__));
++		count = min((int)(iov->iov_len - off), len);
++		memcpy(cp, ((caddr_t)iov->iov_base) + off, count);
++		len -= count;
++		cp += count;
++		off = 0;
++		iol--;
++		iov++;
++	}
++}
++
++void
++cuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
++{
++	struct iovec *iov = uio->uio_iov;
++	int iol = uio->uio_iovcnt;
++	unsigned count;
++
++	CUIO_SKIP();
++	while (len > 0) {
++		KASSERT(iol >= 0, ("%s: empty", __func__));
++		count = min((int)(iov->iov_len - off), len);
++		memcpy(((caddr_t)iov->iov_base) + off, cp, count);
++		len -= count;
++		cp += count;
++		off = 0;
++		iol--;
++		iov++;
++	}
++}
++
++/*
++ * Return a pointer to iov/offset of location in iovec list.
++ */
++struct iovec *
++cuio_getptr(struct uio *uio, int loc, int *off)
++{
++	struct iovec *iov = uio->uio_iov;
++	int iol = uio->uio_iovcnt;
++
++	while (loc >= 0) {
++		/* Normal end of search */
++		if (loc < iov->iov_len) {
++	    		*off = loc;
++	    		return (iov);
++		}
++
++		loc -= iov->iov_len;
++		if (iol == 0) {
++			if (loc == 0) {
++				/* Point at the end of valid data */
++				*off = iov->iov_len;
++				return (iov);
++			} else
++				return (NULL);
++		} else {
++			iov++, iol--;
++		}
++    	}
++
++	return (NULL);
++}
++
++EXPORT_SYMBOL(cuio_copyback);
++EXPORT_SYMBOL(cuio_copydata);
++EXPORT_SYMBOL(cuio_getptr);
++
++
++static void
++skb_copy_bits_back(struct sk_buff *skb, int offset, caddr_t cp, int len)
++{
++	int i;
++	if (offset < skb_headlen(skb)) {
++		memcpy(skb->data + offset, cp, min_t(int, skb_headlen(skb), len));
++		len -= skb_headlen(skb);
++		cp += skb_headlen(skb);
++	}
++	offset -= skb_headlen(skb);
++	for (i = 0; len > 0 && i < skb_shinfo(skb)->nr_frags; i++) {
++		if (offset < skb_shinfo(skb)->frags[i].size) {
++			memcpy(page_address(skb_shinfo(skb)->frags[i].page) +
++					skb_shinfo(skb)->frags[i].page_offset,
++					cp, min_t(int, skb_shinfo(skb)->frags[i].size, len));
++			len -= skb_shinfo(skb)->frags[i].size;
++			cp += skb_shinfo(skb)->frags[i].size;
++		}
++		offset -= skb_shinfo(skb)->frags[i].size;
++	}
++}
++
++void
++crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in)
++{
++
++	if ((flags & CRYPTO_F_SKBUF) != 0)
++		skb_copy_bits_back((struct sk_buff *)buf, off, in, size);
++	else if ((flags & CRYPTO_F_IOV) != 0)
++		cuio_copyback((struct uio *)buf, off, size, in);
++	else
++		bcopy(in, buf + off, size);
++}
++
++void
++crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out)
++{
++
++	if ((flags & CRYPTO_F_SKBUF) != 0)
++		skb_copy_bits((struct sk_buff *)buf, off, out, size);
++	else if ((flags & CRYPTO_F_IOV) != 0)
++		cuio_copydata((struct uio *)buf, off, size, out);
++	else
++		bcopy(buf + off, out, size);
++}
++
++int
++crypto_apply(int flags, caddr_t buf, int off, int len,
++    int (*f)(void *, void *, u_int), void *arg)
++{
++#if 0
++	int error;
++
++	if ((flags & CRYPTO_F_SKBUF) != 0)
++		error = XXXXXX((struct mbuf *)buf, off, len, f, arg);
++	else if ((flags & CRYPTO_F_IOV) != 0)
++		error = cuio_apply((struct uio *)buf, off, len, f, arg);
++	else
++		error = (*f)(arg, buf + off, len);
++	return (error);
++#else
++	KASSERT(0, ("crypto_apply not implemented!\n"));
++#endif
++	return 0;
++}
++
++EXPORT_SYMBOL(crypto_copyback);
++EXPORT_SYMBOL(crypto_copydata);
++EXPORT_SYMBOL(crypto_apply);
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/crypto.c linux-2.6.23.16/crypto/ocf/crypto.c
+--- linux-2.6.23.16.old/crypto/ocf/crypto.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/crypto.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,1715 @@
++/*-
++ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ * The license and original author are listed below.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * Copyright (c) 2002-2006 Sam Leffler.  All rights reserved.
++ *
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#if 0
++#include <sys/cdefs.h>
++__FBSDID("$FreeBSD: src/sys/opencrypto/crypto.c,v 1.27 2007/03/21 03:42:51 sam Exp $");
++#endif
++
++/*
++ * Cryptographic Subsystem.
++ *
++ * This code is derived from the Openbsd Cryptographic Framework (OCF)
++ * that has the copyright shown below.  Very little of the original
++ * code remains.
++ */
++/*-
++ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
++ *
++ * This code was written by Angelos D. Keromytis in Athens, Greece, in
++ * February 2000. Network Security Technologies Inc. (NSTI) kindly
++ * supported the development of this code.
++ *
++ * Copyright (c) 2000, 2001 Angelos D. Keromytis
++ *
++ * Permission to use, copy, and modify this software with or without fee
++ * is hereby granted, provided that this entire notice is included in
++ * all source code copies of any software which is or includes a copy or
++ * modification of this software.
++ *
++ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
++ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
++ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
++ * PURPOSE.
++ *
++__FBSDID("$FreeBSD: src/sys/opencrypto/crypto.c,v 1.16 2005/01/07 02:29:16 imp Exp $");
++ */
++
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/version.h>
++#include <cryptodev.h>
++
++/*
++ * keep track of whether or not we have been initialised, a big
++ * issue if we are linked into the kernel and a driver gets started before
++ * us
++ */
++static int crypto_initted = 0;
++
++/*
++ * Crypto drivers register themselves by allocating a slot in the
++ * crypto_drivers table with crypto_get_driverid() and then registering
++ * each algorithm they support with crypto_register() and crypto_kregister().
++ */
++
++/*
++ * lock on driver table
++ * we track its state as spin_is_locked does not do anything on non-SMP boxes
++ */
++static spinlock_t	crypto_drivers_lock;
++static int			crypto_drivers_locked;		/* for non-SMP boxes */
++
++#define	CRYPTO_DRIVER_LOCK() \
++			({ \
++				spin_lock_irqsave(&crypto_drivers_lock, d_flags); \
++			 	crypto_drivers_locked = 1; \
++				dprintk("%s,%d: DRIVER_LOCK()\n", __FILE__, __LINE__); \
++			 })
++#define	CRYPTO_DRIVER_UNLOCK() \
++			({ \
++			 	dprintk("%s,%d: DRIVER_UNLOCK()\n", __FILE__, __LINE__); \
++			 	crypto_drivers_locked = 0; \
++				spin_unlock_irqrestore(&crypto_drivers_lock, d_flags); \
++			 })
++#define	CRYPTO_DRIVER_ASSERT() \
++			({ \
++			 	if (!crypto_drivers_locked) { \
++					dprintk("%s,%d: DRIVER_ASSERT!\n", __FILE__, __LINE__); \
++			 	} \
++			 })
++
++/*
++ * Crypto device/driver capabilities structure.
++ *
++ * Synchronization:
++ * (d) - protected by CRYPTO_DRIVER_LOCK()
++ * (q) - protected by CRYPTO_Q_LOCK()
++ * Not tagged fields are read-only.
++ */
++struct cryptocap {
++	device_t	cc_dev;			/* (d) device/driver */
++	u_int32_t	cc_sessions;		/* (d) # of sessions */
++	u_int32_t	cc_koperations;		/* (d) # os asym operations */
++	/*
++	 * Largest possible operator length (in bits) for each type of
++	 * encryption algorithm. XXX not used
++	 */
++	u_int16_t	cc_max_op_len[CRYPTO_ALGORITHM_MAX + 1];
++	u_int8_t	cc_alg[CRYPTO_ALGORITHM_MAX + 1];
++	u_int8_t	cc_kalg[CRK_ALGORITHM_MAX + 1];
++
++	int		cc_flags;		/* (d) flags */
++#define CRYPTOCAP_F_CLEANUP	0x80000000	/* needs resource cleanup */
++	int		cc_qblocked;		/* (q) symmetric q blocked */
++	int		cc_kqblocked;		/* (q) asymmetric q blocked */
++};
++static struct cryptocap *crypto_drivers = NULL;
++static int crypto_drivers_num = 0;
++
++/*
++ * There are two queues for crypto requests; one for symmetric (e.g.
++ * cipher) operations and one for asymmetric (e.g. MOD)operations.
++ * A single mutex is used to lock access to both queues.  We could
++ * have one per-queue but having one simplifies handling of block/unblock
++ * operations.
++ */
++static	int crp_sleep = 0;
++static LIST_HEAD(crp_q);		/* request queues */
++static LIST_HEAD(crp_kq);
++
++static spinlock_t crypto_q_lock;
++
++static int crypto_all_qblocked = 0;  /* protect with Q_LOCK */
++static int crypto_all_kqblocked = 0; /* protect with Q_LOCK */
++
++#define	CRYPTO_Q_LOCK() \
++			({ \
++				spin_lock_irqsave(&crypto_q_lock, q_flags); \
++			 	dprintk("%s,%d: Q_LOCK()\n", __FILE__, __LINE__); \
++			 })
++#define	CRYPTO_Q_UNLOCK() \
++			({ \
++			 	dprintk("%s,%d: Q_UNLOCK()\n", __FILE__, __LINE__); \
++				spin_unlock_irqrestore(&crypto_q_lock, q_flags); \
++			 })
++
++/*
++ * There are two queues for processing completed crypto requests; one
++ * for the symmetric and one for the asymmetric ops.  We only need one
++ * but have two to avoid type futzing (cryptop vs. cryptkop).  A single
++ * mutex is used to lock access to both queues.  Note that this lock
++ * must be separate from the lock on request queues to insure driver
++ * callbacks don't generate lock order reversals.
++ */
++static LIST_HEAD(crp_ret_q);		/* callback queues */
++static LIST_HEAD(crp_ret_kq);
++
++static spinlock_t crypto_ret_q_lock;
++#define	CRYPTO_RETQ_LOCK() \
++			({ \
++				spin_lock_irqsave(&crypto_ret_q_lock, r_flags); \
++				dprintk("%s,%d: RETQ_LOCK\n", __FILE__, __LINE__); \
++			 })
++#define	CRYPTO_RETQ_UNLOCK() \
++			({ \
++			 	dprintk("%s,%d: RETQ_UNLOCK\n", __FILE__, __LINE__); \
++				spin_unlock_irqrestore(&crypto_ret_q_lock, r_flags); \
++			 })
++#define	CRYPTO_RETQ_EMPTY()	(list_empty(&crp_ret_q) && list_empty(&crp_ret_kq))
++
++static struct kmem_cache *cryptop_zone;
++static struct kmem_cache *cryptodesc_zone;
++
++#define debug crypto_debug
++int crypto_debug = 0;
++module_param(crypto_debug, int, 0644);
++MODULE_PARM_DESC(crypto_debug, "Enable debug");
++EXPORT_SYMBOL(crypto_debug);
++
++/*
++ * Maximum number of outstanding crypto requests before we start
++ * failing requests.  We need this to prevent DOS when too many
++ * requests are arriving for us to keep up.  Otherwise we will
++ * run the system out of memory.  Since crypto is slow,  we are
++ * usually the bottleneck that needs to say, enough is enough.
++ *
++ * We cannot print errors when this condition occurs,  we are already too
++ * slow,  printing anything will just kill us
++ */
++
++static atomic_t crypto_q_cnt;
++static int crypto_q_max = 1000;
++module_param(crypto_q_max, int, 0644);
++MODULE_PARM_DESC(crypto_q_max,
++		"Maximum number of outstanding crypto requests");
++
++#define bootverbose crypto_verbose
++static int crypto_verbose = 0;
++module_param(crypto_verbose, int, 0644);
++MODULE_PARM_DESC(crypto_verbose,
++		"Enable verbose crypto startup");
++
++int	crypto_usercrypto = 1;	/* userland may do crypto reqs */
++module_param(crypto_usercrypto, int, 0644);
++MODULE_PARM_DESC(crypto_usercrypto,
++	   "Enable/disable user-mode access to crypto support");
++
++int	crypto_userasymcrypto = 1;	/* userland may do asym crypto reqs */
++module_param(crypto_userasymcrypto, int, 0644);
++MODULE_PARM_DESC(crypto_userasymcrypto,
++	   "Enable/disable user-mode access to asymmetric crypto support");
++
++int	crypto_devallowsoft = 0;	/* only use hardware crypto */
++module_param(crypto_devallowsoft, int, 0644);
++MODULE_PARM_DESC(crypto_devallowsoft,
++	   "Enable/disable use of software crypto support");
++
++static pid_t	cryptoproc = (pid_t) -1;
++static struct	completion cryptoproc_exited;
++static DECLARE_WAIT_QUEUE_HEAD(cryptoproc_wait);
++static pid_t	cryptoretproc = (pid_t) -1;
++static struct	completion cryptoretproc_exited;
++static DECLARE_WAIT_QUEUE_HEAD(cryptoretproc_wait);
++
++static	int crypto_proc(void *arg);
++static	int crypto_ret_proc(void *arg);
++static	int crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint);
++static	int crypto_kinvoke(struct cryptkop *krp, int flags);
++static	void crypto_exit(void);
++static  int crypto_init(void);
++
++static	struct cryptostats cryptostats;
++
++static struct cryptocap *
++crypto_checkdriver(u_int32_t hid)
++{
++	if (crypto_drivers == NULL)
++		return NULL;
++	return (hid >= crypto_drivers_num ? NULL : &crypto_drivers[hid]);
++}
++
++/*
++ * Compare a driver's list of supported algorithms against another
++ * list; return non-zero if all algorithms are supported.
++ */
++static int
++driver_suitable(const struct cryptocap *cap, const struct cryptoini *cri)
++{
++	const struct cryptoini *cr;
++
++	/* See if all the algorithms are supported. */
++	for (cr = cri; cr; cr = cr->cri_next)
++		if (cap->cc_alg[cr->cri_alg] == 0)
++			return 0;
++	return 1;
++}
++
++/*
++ * Select a driver for a new session that supports the specified
++ * algorithms and, optionally, is constrained according to the flags.
++ * The algorithm we use here is pretty stupid; just use the
++ * first driver that supports all the algorithms we need. If there
++ * are multiple drivers we choose the driver with the fewest active
++ * sessions.  We prefer hardware-backed drivers to software ones.
++ *
++ * XXX We need more smarts here (in real life too, but that's
++ * XXX another story altogether).
++ */
++static struct cryptocap *
++crypto_select_driver(const struct cryptoini *cri, int flags)
++{
++	struct cryptocap *cap, *best;
++	int match, hid;
++
++	CRYPTO_DRIVER_ASSERT();
++
++	/*
++	 * Look first for hardware crypto devices if permitted.
++	 */
++	if (flags & CRYPTOCAP_F_HARDWARE)
++		match = CRYPTOCAP_F_HARDWARE;
++	else
++		match = CRYPTOCAP_F_SOFTWARE;
++	best = NULL;
++again:
++	for (hid = 0; hid < crypto_drivers_num; hid++) {
++		cap = &crypto_drivers[hid];
++		/*
++		 * If it's not initialized, is in the process of
++		 * going away, or is not appropriate (hardware
++		 * or software based on match), then skip.
++		 */
++		if (cap->cc_dev == NULL ||
++		    (cap->cc_flags & CRYPTOCAP_F_CLEANUP) ||
++		    (cap->cc_flags & match) == 0)
++			continue;
++
++		/* verify all the algorithms are supported. */
++		if (driver_suitable(cap, cri)) {
++			if (best == NULL ||
++			    cap->cc_sessions < best->cc_sessions)
++				best = cap;
++		}
++	}
++	if (best != NULL)
++		return best;
++	if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
++		/* sort of an Algol 68-style for loop */
++		match = CRYPTOCAP_F_SOFTWARE;
++		goto again;
++	}
++	return best;
++}
++
++/*
++ * Create a new session.  The crid argument specifies a crypto
++ * driver to use or constraints on a driver to select (hardware
++ * only, software only, either).  Whatever driver is selected
++ * must be capable of the requested crypto algorithms.
++ */
++int
++crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid)
++{
++	struct cryptocap *cap;
++	u_int32_t hid, lid;
++	int err;
++	unsigned long d_flags;
++
++	CRYPTO_DRIVER_LOCK();
++	if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
++		/*
++		 * Use specified driver; verify it is capable.
++		 */
++		cap = crypto_checkdriver(crid);
++		if (cap != NULL && !driver_suitable(cap, cri))
++			cap = NULL;
++	} else {
++		/*
++		 * No requested driver; select based on crid flags.
++		 */
++		cap = crypto_select_driver(cri, crid);
++		/*
++		 * if NULL then can't do everything in one session.
++		 * XXX Fix this. We need to inject a "virtual" session
++		 * XXX layer right about here.
++		 */
++	}
++	if (cap != NULL) {
++		/* Call the driver initialization routine. */
++		hid = cap - crypto_drivers;
++		lid = hid;		/* Pass the driver ID. */
++		cap->cc_sessions++;
++		CRYPTO_DRIVER_UNLOCK();
++		err = CRYPTODEV_NEWSESSION(cap->cc_dev, &lid, cri);
++		CRYPTO_DRIVER_LOCK();
++		if (err == 0) {
++			(*sid) = (cap->cc_flags & 0xff000000)
++			       | (hid & 0x00ffffff);
++			(*sid) <<= 32;
++			(*sid) |= (lid & 0xffffffff);
++		} else
++			cap->cc_sessions--;
++	} else
++		err = EINVAL;
++	CRYPTO_DRIVER_UNLOCK();
++	return err;
++}
++
++static void
++crypto_remove(struct cryptocap *cap)
++{
++	CRYPTO_DRIVER_ASSERT();
++	if (cap->cc_sessions == 0 && cap->cc_koperations == 0)
++		bzero(cap, sizeof(*cap));
++}
++
++/*
++ * Delete an existing session (or a reserved session on an unregistered
++ * driver).
++ */
++int
++crypto_freesession(u_int64_t sid)
++{
++	struct cryptocap *cap;
++	u_int32_t hid;
++	int err;
++	unsigned long d_flags;
++
++	dprintk("%s()\n", __FUNCTION__);
++	CRYPTO_DRIVER_LOCK();
++
++	if (crypto_drivers == NULL) {
++		err = EINVAL;
++		goto done;
++	}
++
++	/* Determine two IDs. */
++	hid = CRYPTO_SESID2HID(sid);
++
++	if (hid >= crypto_drivers_num) {
++		dprintk("%s - INVALID DRIVER NUM %d\n", __FUNCTION__, hid);
++		err = ENOENT;
++		err = ENOENT;
++		goto done;
++	}
++	cap = &crypto_drivers[hid];
++
++	if (cap->cc_dev) {
++		CRYPTO_DRIVER_UNLOCK();
++		/* Call the driver cleanup routine, if available, unlocked. */
++		err = CRYPTODEV_FREESESSION(cap->cc_dev, sid);
++		CRYPTO_DRIVER_LOCK();
++	}
++
++	if (cap->cc_sessions)
++		cap->cc_sessions--;
++
++	if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
++		crypto_remove(cap);
++
++done:
++	CRYPTO_DRIVER_UNLOCK();
++	return err;
++}
++
++/*
++ * Return an unused driver id.  Used by drivers prior to registering
++ * support for the algorithms they handle.
++ */
++int32_t
++crypto_get_driverid(device_t dev, int flags)
++{
++	struct cryptocap *newdrv;
++	int i;
++	unsigned long d_flags;
++
++	if ((flags & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
++		printf("%s: no flags specified when registering driver\n",
++		    device_get_nameunit(dev));
++		return -1;
++	}
++
++	CRYPTO_DRIVER_LOCK();
++
++	for (i = 0; i < crypto_drivers_num; i++) {
++		if (crypto_drivers[i].cc_dev == NULL &&
++		    (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP) == 0) {
++			break;
++		}
++	}
++
++	/* Out of entries, allocate some more. */
++	if (i == crypto_drivers_num) {
++		/* Be careful about wrap-around. */
++		if (2 * crypto_drivers_num <= crypto_drivers_num) {
++			CRYPTO_DRIVER_UNLOCK();
++			printk("crypto: driver count wraparound!\n");
++			return -1;
++		}
++
++		newdrv = kmalloc(2 * crypto_drivers_num * sizeof(struct cryptocap),
++				GFP_KERNEL);
++		if (newdrv == NULL) {
++			CRYPTO_DRIVER_UNLOCK();
++			printk("crypto: no space to expand driver table!\n");
++			return -1;
++		}
++
++		memcpy(newdrv, crypto_drivers,
++				crypto_drivers_num * sizeof(struct cryptocap));
++		memset(&newdrv[crypto_drivers_num], 0,
++				crypto_drivers_num * sizeof(struct cryptocap));
++
++		crypto_drivers_num *= 2;
++
++		kfree(crypto_drivers);
++		crypto_drivers = newdrv;
++	}
++
++	/* NB: state is zero'd on free */
++	crypto_drivers[i].cc_sessions = 1;	/* Mark */
++	crypto_drivers[i].cc_dev = dev;
++	crypto_drivers[i].cc_flags = flags;
++	if (bootverbose)
++		printf("crypto: assign %s driver id %u, flags %u\n",
++		    device_get_nameunit(dev), i, flags);
++
++	CRYPTO_DRIVER_UNLOCK();
++
++	return i;
++}
++
++/*
++ * Lookup a driver by name.  We match against the full device
++ * name and unit, and against just the name.  The latter gives
++ * us a simple widlcarding by device name.  On success return the
++ * driver/hardware identifier; otherwise return -1.
++ */
++int
++crypto_find_driver(const char *match)
++{
++	int i, len = strlen(match);
++	unsigned long d_flags;
++
++	CRYPTO_DRIVER_LOCK();
++	for (i = 0; i < crypto_drivers_num; i++) {
++		device_t dev = crypto_drivers[i].cc_dev;
++		if (dev == NULL ||
++		    (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP))
++			continue;
++		if (strncmp(match, device_get_nameunit(dev), len) == 0 ||
++		    strncmp(match, device_get_name(dev), len) == 0)
++			break;
++	}
++	CRYPTO_DRIVER_UNLOCK();
++	return i < crypto_drivers_num ? i : -1;
++}
++
++/*
++ * Return the device_t for the specified driver or NULL
++ * if the driver identifier is invalid.
++ */
++device_t
++crypto_find_device_byhid(int hid)
++{
++	struct cryptocap *cap = crypto_checkdriver(hid);
++	return cap != NULL ? cap->cc_dev : NULL;
++}
++
++/*
++ * Return the device/driver capabilities.
++ */
++int
++crypto_getcaps(int hid)
++{
++	struct cryptocap *cap = crypto_checkdriver(hid);
++	return cap != NULL ? cap->cc_flags : 0;
++}
++
++/*
++ * Register support for a key-related algorithm.  This routine
++ * is called once for each algorithm supported a driver.
++ */
++int
++crypto_kregister(u_int32_t driverid, int kalg, u_int32_t flags)
++{
++	struct cryptocap *cap;
++	int err;
++	unsigned long d_flags;
++
++	dprintk("%s()\n", __FUNCTION__);
++	CRYPTO_DRIVER_LOCK();
++
++	cap = crypto_checkdriver(driverid);
++	if (cap != NULL &&
++	    (CRK_ALGORITM_MIN <= kalg && kalg <= CRK_ALGORITHM_MAX)) {
++		/*
++		 * XXX Do some performance testing to determine placing.
++		 * XXX We probably need an auxiliary data structure that
++		 * XXX describes relative performances.
++		 */
++
++		cap->cc_kalg[kalg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
++		if (bootverbose)
++			printf("crypto: %s registers key alg %u flags %u\n"
++				, device_get_nameunit(cap->cc_dev)
++				, kalg
++				, flags
++			);
++		err = 0;
++	} else
++		err = EINVAL;
++
++	CRYPTO_DRIVER_UNLOCK();
++	return err;
++}
++
++/*
++ * Register support for a non-key-related algorithm.  This routine
++ * is called once for each such algorithm supported by a driver.
++ */
++int
++crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
++    u_int32_t flags)
++{
++	struct cryptocap *cap;
++	int err;
++	unsigned long d_flags;
++
++	dprintk("%s(id=0x%x, alg=%d, maxoplen=%d, flags=0x%x)\n", __FUNCTION__,
++			driverid, alg, maxoplen, flags);
++
++	CRYPTO_DRIVER_LOCK();
++
++	cap = crypto_checkdriver(driverid);
++	/* NB: algorithms are in the range [1..max] */
++	if (cap != NULL &&
++	    (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX)) {
++		/*
++		 * XXX Do some performance testing to determine placing.
++		 * XXX We probably need an auxiliary data structure that
++		 * XXX describes relative performances.
++		 */
++
++		cap->cc_alg[alg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
++		cap->cc_max_op_len[alg] = maxoplen;
++		if (bootverbose)
++			printf("crypto: %s registers alg %u flags %u maxoplen %u\n"
++				, device_get_nameunit(cap->cc_dev)
++				, alg
++				, flags
++				, maxoplen
++			);
++		cap->cc_sessions = 0;		/* Unmark */
++		err = 0;
++	} else
++		err = EINVAL;
++
++	CRYPTO_DRIVER_UNLOCK();
++	return err;
++}
++
++static void
++driver_finis(struct cryptocap *cap)
++{
++	u_int32_t ses, kops;
++
++	CRYPTO_DRIVER_ASSERT();
++
++	ses = cap->cc_sessions;
++	kops = cap->cc_koperations;
++	bzero(cap, sizeof(*cap));
++	if (ses != 0 || kops != 0) {
++		/*
++		 * If there are pending sessions,
++		 * just mark as invalid.
++		 */
++		cap->cc_flags |= CRYPTOCAP_F_CLEANUP;
++		cap->cc_sessions = ses;
++		cap->cc_koperations = kops;
++	}
++}
++
++/*
++ * Unregister a crypto driver. If there are pending sessions using it,
++ * leave enough information around so that subsequent calls using those
++ * sessions will correctly detect the driver has been unregistered and
++ * reroute requests.
++ */
++int
++crypto_unregister(u_int32_t driverid, int alg)
++{
++	struct cryptocap *cap;
++	int i, err;
++	unsigned long d_flags;
++
++	dprintk("%s()\n", __FUNCTION__);
++	CRYPTO_DRIVER_LOCK();
++
++	cap = crypto_checkdriver(driverid);
++	if (cap != NULL &&
++	    (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX) &&
++	    cap->cc_alg[alg] != 0) {
++		cap->cc_alg[alg] = 0;
++		cap->cc_max_op_len[alg] = 0;
++
++		/* Was this the last algorithm ? */
++		for (i = 1; i <= CRYPTO_ALGORITHM_MAX; i++)
++			if (cap->cc_alg[i] != 0)
++				break;
++
++		if (i == CRYPTO_ALGORITHM_MAX + 1)
++			driver_finis(cap);
++		err = 0;
++	} else
++		err = EINVAL;
++	CRYPTO_DRIVER_UNLOCK();
++	return err;
++}
++
++/*
++ * Unregister all algorithms associated with a crypto driver.
++ * If there are pending sessions using it, leave enough information
++ * around so that subsequent calls using those sessions will
++ * correctly detect the driver has been unregistered and reroute
++ * requests.
++ */
++int
++crypto_unregister_all(u_int32_t driverid)
++{
++	struct cryptocap *cap;
++	int err;
++	unsigned long d_flags;
++
++	dprintk("%s()\n", __FUNCTION__);
++	CRYPTO_DRIVER_LOCK();
++	cap = crypto_checkdriver(driverid);
++	if (cap != NULL) {
++		driver_finis(cap);
++		err = 0;
++	} else
++		err = EINVAL;
++	CRYPTO_DRIVER_UNLOCK();
++
++	return err;
++}
++
++/*
++ * Clear blockage on a driver.  The what parameter indicates whether
++ * the driver is now ready for cryptop's and/or cryptokop's.
++ */
++int
++crypto_unblock(u_int32_t driverid, int what)
++{
++	struct cryptocap *cap;
++	int err;
++	unsigned long q_flags;
++
++	CRYPTO_Q_LOCK();
++	cap = crypto_checkdriver(driverid);
++	if (cap != NULL) {
++		if (what & CRYPTO_SYMQ) {
++			cap->cc_qblocked = 0;
++			crypto_all_qblocked = 0;
++		}
++		if (what & CRYPTO_ASYMQ) {
++			cap->cc_kqblocked = 0;
++			crypto_all_kqblocked = 0;
++		}
++		if (crp_sleep)
++			wake_up_interruptible(&cryptoproc_wait);
++		err = 0;
++	} else
++		err = EINVAL;
++	CRYPTO_Q_UNLOCK(); //DAVIDM should this be a driver lock
++
++	return err;
++}
++
++/*
++ * Add a crypto request to a queue, to be processed by the kernel thread.
++ */
++int
++crypto_dispatch(struct cryptop *crp)
++{
++	struct cryptocap *cap;
++	u_int32_t hid;
++	int result;
++	unsigned long q_flags;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	cryptostats.cs_ops++;
++
++	if (atomic_read(&crypto_q_cnt) >= crypto_q_max) {
++		cryptostats.cs_drops++;
++		return ENOMEM;
++	}
++	atomic_inc(&crypto_q_cnt);
++
++	hid = CRYPTO_SESID2HID(crp->crp_sid);
++
++	if ((crp->crp_flags & CRYPTO_F_BATCH) == 0) {
++		/*
++		 * Caller marked the request to be processed
++		 * immediately; dispatch it directly to the
++		 * driver unless the driver is currently blocked.
++		 */
++		cap = crypto_checkdriver(hid);
++		/* Driver cannot disappeared when there is an active session. */
++		KASSERT(cap != NULL, ("%s: Driver disappeared.", __func__));
++		if (!cap->cc_qblocked) {
++			result = crypto_invoke(cap, crp, 0);
++			if (result != ERESTART)
++				return (result);
++			/*
++			 * The driver ran out of resources, put the request on
++			 * the queue.
++			 */
++		}
++	}
++	CRYPTO_Q_LOCK();
++	TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
++	if (crp_sleep)
++		wake_up_interruptible(&cryptoproc_wait);
++	CRYPTO_Q_UNLOCK();
++	return 0;
++}
++
++/*
++ * Add an asymetric crypto request to a queue,
++ * to be processed by the kernel thread.
++ */
++int
++crypto_kdispatch(struct cryptkop *krp)
++{
++	int error;
++	unsigned long q_flags;
++
++	cryptostats.cs_kops++;
++
++	error = crypto_kinvoke(krp, krp->krp_crid);
++	if (error == ERESTART) {
++		CRYPTO_Q_LOCK();
++		TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
++		if (crp_sleep)
++			wake_up_interruptible(&cryptoproc_wait);
++		CRYPTO_Q_UNLOCK();
++		error = 0;
++	}
++	return error;
++}
++
++/*
++ * Verify a driver is suitable for the specified operation.
++ */
++static __inline int
++kdriver_suitable(const struct cryptocap *cap, const struct cryptkop *krp)
++{
++	return (cap->cc_kalg[krp->krp_op] & CRYPTO_ALG_FLAG_SUPPORTED) != 0;
++}
++
++/*
++ * Select a driver for an asym operation.  The driver must
++ * support the necessary algorithm.  The caller can constrain
++ * which device is selected with the flags parameter.  The
++ * algorithm we use here is pretty stupid; just use the first
++ * driver that supports the algorithms we need. If there are
++ * multiple suitable drivers we choose the driver with the
++ * fewest active operations.  We prefer hardware-backed
++ * drivers to software ones when either may be used.
++ */
++static struct cryptocap *
++crypto_select_kdriver(const struct cryptkop *krp, int flags)
++{
++	struct cryptocap *cap, *best, *blocked;
++	int match, hid;
++
++	CRYPTO_DRIVER_ASSERT();
++
++	/*
++	 * Look first for hardware crypto devices if permitted.
++	 */
++	if (flags & CRYPTOCAP_F_HARDWARE)
++		match = CRYPTOCAP_F_HARDWARE;
++	else
++		match = CRYPTOCAP_F_SOFTWARE;
++	best = NULL;
++	blocked = NULL;
++again:
++	for (hid = 0; hid < crypto_drivers_num; hid++) {
++		cap = &crypto_drivers[hid];
++		/*
++		 * If it's not initialized, is in the process of
++		 * going away, or is not appropriate (hardware
++		 * or software based on match), then skip.
++		 */
++		if (cap->cc_dev == NULL ||
++		    (cap->cc_flags & CRYPTOCAP_F_CLEANUP) ||
++		    (cap->cc_flags & match) == 0)
++			continue;
++
++		/* verify all the algorithms are supported. */
++		if (kdriver_suitable(cap, krp)) {
++			if (best == NULL ||
++			    cap->cc_koperations < best->cc_koperations)
++				best = cap;
++		}
++	}
++	if (best != NULL)
++		return best;
++	if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
++		/* sort of an Algol 68-style for loop */
++		match = CRYPTOCAP_F_SOFTWARE;
++		goto again;
++	}
++	return best;
++}
++
++/*
++ * Dispatch an assymetric crypto request.
++ */
++static int
++crypto_kinvoke(struct cryptkop *krp, int crid)
++{
++	struct cryptocap *cap = NULL;
++	int error;
++	unsigned long d_flags;
++
++	KASSERT(krp != NULL, ("%s: krp == NULL", __func__));
++	KASSERT(krp->krp_callback != NULL,
++	    ("%s: krp->crp_callback == NULL", __func__));
++
++	CRYPTO_DRIVER_LOCK();
++	if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
++		cap = crypto_checkdriver(crid);
++		if (cap != NULL) {
++			/*
++			 * Driver present, it must support the necessary
++			 * algorithm and, if s/w drivers are excluded,
++			 * it must be registered as hardware-backed.
++			 */
++			if (!kdriver_suitable(cap, krp) ||
++			    (!crypto_devallowsoft &&
++			     (cap->cc_flags & CRYPTOCAP_F_HARDWARE) == 0))
++				cap = NULL;
++		}
++	} else {
++		/*
++		 * No requested driver; select based on crid flags.
++		 */
++		if (!crypto_devallowsoft)	/* NB: disallow s/w drivers */
++			crid &= ~CRYPTOCAP_F_SOFTWARE;
++		cap = crypto_select_kdriver(krp, crid);
++	}
++	if (cap != NULL && !cap->cc_kqblocked) {
++		krp->krp_hid = cap - crypto_drivers;
++		cap->cc_koperations++;
++		CRYPTO_DRIVER_UNLOCK();
++		error = CRYPTODEV_KPROCESS(cap->cc_dev, krp, 0);
++		CRYPTO_DRIVER_LOCK();
++		if (error == ERESTART) {
++			cap->cc_koperations--;
++			CRYPTO_DRIVER_UNLOCK();
++			return (error);
++		}
++		/* return the actual device used */
++		krp->krp_crid = krp->krp_hid;
++	} else {
++		/*
++		 * NB: cap is !NULL if device is blocked; in
++		 *     that case return ERESTART so the operation
++		 *     is resubmitted if possible.
++		 */
++		error = (cap == NULL) ? ENODEV : ERESTART;
++	}
++	CRYPTO_DRIVER_UNLOCK();
++
++	if (error) {
++		krp->krp_status = error;
++		crypto_kdone(krp);
++	}
++	return 0;
++}
++
++
++/*
++ * Dispatch a crypto request to the appropriate crypto devices.
++ */
++static int
++crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint)
++{
++
++	KASSERT(crp != NULL, ("%s: crp == NULL", __func__));
++	KASSERT(crp->crp_callback != NULL,
++	    ("%s: crp->crp_callback == NULL", __func__));
++	KASSERT(crp->crp_desc != NULL, ("%s: crp->crp_desc == NULL", __func__));
++
++	dprintk("%s()\n", __FUNCTION__);
++
++#ifdef CRYPTO_TIMING
++	if (crypto_timing)
++		crypto_tstat(&cryptostats.cs_invoke, &crp->crp_tstamp);
++#endif
++	if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) {
++		struct cryptodesc *crd;
++		u_int64_t nid;
++
++		/*
++		 * Driver has unregistered; migrate the session and return
++		 * an error to the caller so they'll resubmit the op.
++		 *
++		 * XXX: What if there are more already queued requests for this
++		 *      session?
++		 */
++		crypto_freesession(crp->crp_sid);
++
++		for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)
++			crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);
++
++		/* XXX propagate flags from initial session? */
++		if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI),
++		    CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE) == 0)
++			crp->crp_sid = nid;
++
++		crp->crp_etype = EAGAIN;
++		crypto_done(crp);
++		return 0;
++	} else {
++		/*
++		 * Invoke the driver to process the request.
++		 */
++		return CRYPTODEV_PROCESS(cap->cc_dev, crp, hint);
++	}
++}
++
++/*
++ * Release a set of crypto descriptors.
++ */
++void
++crypto_freereq(struct cryptop *crp)
++{
++	struct cryptodesc *crd;
++
++	if (crp == NULL)
++		return;
++
++#ifdef DIAGNOSTIC
++	{
++		struct cryptop *crp2;
++		unsigned long q_flags;
++
++		CRYPTO_Q_LOCK();
++		TAILQ_FOREACH(crp2, &crp_q, crp_next) {
++			KASSERT(crp2 != crp,
++			    ("Freeing cryptop from the crypto queue (%p).",
++			    crp));
++		}
++		CRYPTO_Q_UNLOCK();
++		CRYPTO_RETQ_LOCK();
++		TAILQ_FOREACH(crp2, &crp_ret_q, crp_next) {
++			KASSERT(crp2 != crp,
++			    ("Freeing cryptop from the return queue (%p).",
++			    crp));
++		}
++		CRYPTO_RETQ_UNLOCK();
++	}
++#endif
++
++	while ((crd = crp->crp_desc) != NULL) {
++		crp->crp_desc = crd->crd_next;
++		kmem_cache_free(cryptodesc_zone, crd);
++	}
++	kmem_cache_free(cryptop_zone, crp);
++}
++
++/*
++ * Acquire a set of crypto descriptors.
++ */
++struct cryptop *
++crypto_getreq(int num)
++{
++	struct cryptodesc *crd;
++	struct cryptop *crp;
++
++	crp = kmem_cache_alloc(cryptop_zone, SLAB_ATOMIC);
++	if (crp != NULL) {
++		memset(crp, 0, sizeof(*crp));
++		INIT_LIST_HEAD(&crp->crp_next);
++		init_waitqueue_head(&crp->crp_waitq);
++		while (num--) {
++			crd = kmem_cache_alloc(cryptodesc_zone, SLAB_ATOMIC);
++			if (crd == NULL) {
++				crypto_freereq(crp);
++				return NULL;
++			}
++			memset(crd, 0, sizeof(*crd));
++			crd->crd_next = crp->crp_desc;
++			crp->crp_desc = crd;
++		}
++	}
++	return crp;
++}
++
++/*
++ * Invoke the callback on behalf of the driver.
++ */
++void
++crypto_done(struct cryptop *crp)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	if ((crp->crp_flags & CRYPTO_F_DONE) == 0) {
++		crp->crp_flags |= CRYPTO_F_DONE;
++		atomic_dec(&crypto_q_cnt);
++	} else
++		printk("crypto: crypto_done op already done, flags 0x%x",
++				crp->crp_flags);
++	if (crp->crp_etype != 0)
++		cryptostats.cs_errs++;
++	/*
++	 * CBIMM means unconditionally do the callback immediately;
++	 * CBIFSYNC means do the callback immediately only if the
++	 * operation was done synchronously.  Both are used to avoid
++	 * doing extraneous context switches; the latter is mostly
++	 * used with the software crypto driver.
++	 */
++	if ((crp->crp_flags & CRYPTO_F_CBIMM) ||
++	    ((crp->crp_flags & CRYPTO_F_CBIFSYNC) &&
++	     (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC))) {
++		/*
++		 * Do the callback directly.  This is ok when the
++		 * callback routine does very little (e.g. the
++		 * /dev/crypto callback method just does a wakeup).
++		 */
++		crp->crp_callback(crp);
++	} else {
++		unsigned long r_flags;
++		/*
++		 * Normal case; queue the callback for the thread.
++		 */
++		CRYPTO_RETQ_LOCK();
++		if (CRYPTO_RETQ_EMPTY())
++			wake_up_interruptible(&cryptoretproc_wait);/* shared wait channel */
++		TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
++		CRYPTO_RETQ_UNLOCK();
++	}
++}
++
++/*
++ * Invoke the callback on behalf of the driver.
++ */
++void
++crypto_kdone(struct cryptkop *krp)
++{
++	struct cryptocap *cap;
++	unsigned long d_flags;
++
++	if ((krp->krp_flags & CRYPTO_KF_DONE) != 0)
++		printk("crypto: crypto_kdone op already done, flags 0x%x",
++				krp->krp_flags);
++	krp->krp_flags |= CRYPTO_KF_DONE;
++	if (krp->krp_status != 0)
++		cryptostats.cs_kerrs++;
++
++	CRYPTO_DRIVER_LOCK();
++	/* XXX: What if driver is loaded in the meantime? */
++	if (krp->krp_hid < crypto_drivers_num) {
++		cap = &crypto_drivers[krp->krp_hid];
++		cap->cc_koperations--;
++		KASSERT(cap->cc_koperations >= 0, ("cc_koperations < 0"));
++		if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
++			crypto_remove(cap);
++	}
++	CRYPTO_DRIVER_UNLOCK();
++
++	/*
++	 * CBIMM means unconditionally do the callback immediately;
++	 * This is used to avoid doing extraneous context switches
++	 */
++	if ((krp->krp_flags & CRYPTO_KF_CBIMM)) {
++		/*
++		 * Do the callback directly.  This is ok when the
++		 * callback routine does very little (e.g. the
++		 * /dev/crypto callback method just does a wakeup).
++		 */
++		krp->krp_callback(krp);
++	} else {
++		unsigned long r_flags;
++		/*
++		 * Normal case; queue the callback for the thread.
++		 */
++		CRYPTO_RETQ_LOCK();
++		if (CRYPTO_RETQ_EMPTY())
++			wake_up_interruptible(&cryptoretproc_wait);/* shared wait channel */
++		TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
++		CRYPTO_RETQ_UNLOCK();
++	}
++}
++
++int
++crypto_getfeat(int *featp)
++{
++	int hid, kalg, feat = 0;
++	unsigned long d_flags;
++
++	CRYPTO_DRIVER_LOCK();
++	for (hid = 0; hid < crypto_drivers_num; hid++) {
++		const struct cryptocap *cap = &crypto_drivers[hid];
++
++		if ((cap->cc_flags & CRYPTOCAP_F_SOFTWARE) &&
++		    !crypto_devallowsoft) {
++			continue;
++		}
++		for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
++			if (cap->cc_kalg[kalg] & CRYPTO_ALG_FLAG_SUPPORTED)
++				feat |=  1 << kalg;
++	}
++	CRYPTO_DRIVER_UNLOCK();
++	*featp = feat;
++	return (0);
++}
++
++/*
++ * Crypto thread, dispatches crypto requests.
++ */
++static int
++crypto_proc(void *arg)
++{
++	struct cryptop *crp, *submit;
++	struct cryptkop *krp, *krpp;
++	struct cryptocap *cap;
++	u_int32_t hid;
++	int result, hint;
++	unsigned long q_flags;
++
++	ocf_daemonize("crypto");
++
++	CRYPTO_Q_LOCK();
++	for (;;) {
++		/*
++		 * we need to make sure we don't get into a busy loop with nothing
++		 * to do,  the two crypto_all_*blocked vars help us find out when
++		 * we are all full and can do nothing on any driver or Q.  If so we
++		 * wait for an unblock.
++		 */
++		crypto_all_qblocked  = !list_empty(&crp_q);
++
++		/*
++		 * Find the first element in the queue that can be
++		 * processed and look-ahead to see if multiple ops
++		 * are ready for the same driver.
++		 */
++		submit = NULL;
++		hint = 0;
++		list_for_each_entry(crp, &crp_q, crp_next) {
++			hid = CRYPTO_SESID2HID(crp->crp_sid);
++			cap = crypto_checkdriver(hid);
++			/*
++			 * Driver cannot disappeared when there is an active
++			 * session.
++			 */
++			KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
++			    __func__, __LINE__));
++			if (cap == NULL || cap->cc_dev == NULL) {
++				/* Op needs to be migrated, process it. */
++				if (submit == NULL)
++					submit = crp;
++				break;
++			}
++			if (!cap->cc_qblocked) {
++				if (submit != NULL) {
++					/*
++					 * We stop on finding another op,
++					 * regardless whether its for the same
++					 * driver or not.  We could keep
++					 * searching the queue but it might be
++					 * better to just use a per-driver
++					 * queue instead.
++					 */
++					if (CRYPTO_SESID2HID(submit->crp_sid) == hid)
++						hint = CRYPTO_HINT_MORE;
++					break;
++				} else {
++					submit = crp;
++					if ((submit->crp_flags & CRYPTO_F_BATCH) == 0)
++						break;
++					/* keep scanning for more are q'd */
++				}
++			}
++		}
++		if (submit != NULL) {
++			crypto_all_qblocked = 0;
++			list_del(&submit->crp_next);
++			crypto_drivers[CRYPTO_SESID2HID(submit->crp_sid)].cc_qblocked = 1;
++			CRYPTO_Q_UNLOCK();
++			hid = CRYPTO_SESID2HID(submit->crp_sid);
++			cap = crypto_checkdriver(hid);
++			KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
++			    __func__, __LINE__));
++			result = crypto_invoke(cap, submit, hint);
++			CRYPTO_Q_LOCK();
++			if (result == ERESTART) {
++				/*
++				 * The driver ran out of resources, mark the
++				 * driver ``blocked'' for cryptop's and put
++				 * the request back in the queue.  It would
++				 * best to put the request back where we got
++				 * it but that's hard so for now we put it
++				 * at the front.  This should be ok; putting
++				 * it at the end does not work.
++				 */
++				/* XXX validate sid again? */
++				list_add(&submit->crp_next, &crp_q);
++				cryptostats.cs_blocks++;
++			} else
++				crypto_drivers[CRYPTO_SESID2HID(submit->crp_sid)].cc_qblocked=0;
++		}
++
++		crypto_all_kqblocked = !list_empty(&crp_kq);
++
++		/* As above, but for key ops */
++		krp = NULL;
++		list_for_each_entry(krpp, &crp_kq, krp_next) {
++			cap = crypto_checkdriver(krpp->krp_hid);
++			if (cap == NULL || cap->cc_dev == NULL) {
++				/*
++				 * Operation needs to be migrated, invalidate
++				 * the assigned device so it will reselect a
++				 * new one below.  Propagate the original
++				 * crid selection flags if supplied.
++				 */
++				krp->krp_hid = krp->krp_crid &
++				    (CRYPTOCAP_F_SOFTWARE|CRYPTOCAP_F_HARDWARE);
++				if (krp->krp_hid == 0)
++					krp->krp_hid =
++				    CRYPTOCAP_F_SOFTWARE|CRYPTOCAP_F_HARDWARE;
++				break;
++			}
++			if (!cap->cc_kqblocked) {
++				krp = krpp;
++				break;
++			}
++		}
++		if (krp != NULL) {
++			crypto_all_kqblocked = 0;
++			list_del(&krp->krp_next);
++			crypto_drivers[krp->krp_hid].cc_kqblocked = 1;
++			CRYPTO_Q_UNLOCK();
++			result = crypto_kinvoke(krp, krp->krp_hid);
++			CRYPTO_Q_LOCK();
++			if (result == ERESTART) {
++				/*
++				 * The driver ran out of resources, mark the
++				 * driver ``blocked'' for cryptkop's and put
++				 * the request back in the queue.  It would
++				 * best to put the request back where we got
++				 * it but that's hard so for now we put it
++				 * at the front.  This should be ok; putting
++				 * it at the end does not work.
++				 */
++				/* XXX validate sid again? */
++				list_add(&krp->krp_next, &crp_kq);
++				cryptostats.cs_kblocks++;
++			} else
++				crypto_drivers[krp->krp_hid].cc_kqblocked = 0;
++		}
++
++		if (submit == NULL && krp == NULL) {
++			/*
++			 * Nothing more to be processed.  Sleep until we're
++			 * woken because there are more ops to process.
++			 * This happens either by submission or by a driver
++			 * becoming unblocked and notifying us through
++			 * crypto_unblock.  Note that when we wakeup we
++			 * start processing each queue again from the
++			 * front. It's not clear that it's important to
++			 * preserve this ordering since ops may finish
++			 * out of order if dispatched to different devices
++			 * and some become blocked while others do not.
++			 */
++			dprintk("%s - sleeping (qe=%d qb=%d kqe=%d kqb=%d)\n",
++					__FUNCTION__,
++					list_empty(&crp_q), crypto_all_qblocked,
++					list_empty(&crp_kq), crypto_all_kqblocked);
++			CRYPTO_Q_UNLOCK();
++			crp_sleep = 1;
++			wait_event_interruptible(cryptoproc_wait,
++					!(list_empty(&crp_q) || crypto_all_qblocked) ||
++					!(list_empty(&crp_kq) || crypto_all_kqblocked) ||
++					cryptoproc == (pid_t) -1);
++			crp_sleep = 0;
++			if (signal_pending (current)) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++				spin_lock_irq(&current->sigmask_lock);
++#endif
++				flush_signals(current);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++				spin_unlock_irq(&current->sigmask_lock);
++#endif
++			}
++			CRYPTO_Q_LOCK();
++			dprintk("%s - awake\n", __FUNCTION__);
++			if (cryptoproc == (pid_t) -1)
++				break;
++			cryptostats.cs_intrs++;
++		}
++	}
++	CRYPTO_Q_UNLOCK();
++	complete_and_exit(&cryptoproc_exited, 0);
++}
++
++/*
++ * Crypto returns thread, does callbacks for processed crypto requests.
++ * Callbacks are done here, rather than in the crypto drivers, because
++ * callbacks typically are expensive and would slow interrupt handling.
++ */
++static int
++crypto_ret_proc(void *arg)
++{
++	struct cryptop *crpt;
++	struct cryptkop *krpt;
++	unsigned long  r_flags;
++
++	ocf_daemonize("crypto_ret");
++
++	CRYPTO_RETQ_LOCK();
++	for (;;) {
++		/* Harvest return q's for completed ops */
++		crpt = NULL;
++		if (!list_empty(&crp_ret_q))
++			crpt = list_entry(crp_ret_q.next, typeof(*crpt), crp_next);
++		if (crpt != NULL)
++			list_del(&crpt->crp_next);
++
++		krpt = NULL;
++		if (!list_empty(&crp_ret_kq))
++			krpt = list_entry(crp_ret_kq.next, typeof(*krpt), krp_next);
++		if (krpt != NULL)
++			list_del(&krpt->krp_next);
++
++		if (crpt != NULL || krpt != NULL) {
++			CRYPTO_RETQ_UNLOCK();
++			/*
++			 * Run callbacks unlocked.
++			 */
++			if (crpt != NULL)
++				crpt->crp_callback(crpt);
++			if (krpt != NULL)
++				krpt->krp_callback(krpt);
++			CRYPTO_RETQ_LOCK();
++		} else {
++			/*
++			 * Nothing more to be processed.  Sleep until we're
++			 * woken because there are more returns to process.
++			 */
++			dprintk("%s - sleeping\n", __FUNCTION__);
++			CRYPTO_RETQ_UNLOCK();
++			wait_event_interruptible(cryptoretproc_wait,
++					cryptoretproc == (pid_t) -1 ||
++					!list_empty(&crp_ret_q) ||
++					!list_empty(&crp_ret_kq));
++			if (signal_pending (current)) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++				spin_lock_irq(&current->sigmask_lock);
++#endif
++				flush_signals(current);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++				spin_unlock_irq(&current->sigmask_lock);
++#endif
++			}
++			CRYPTO_RETQ_LOCK();
++			dprintk("%s - awake\n", __FUNCTION__);
++			if (cryptoretproc == (pid_t) -1) {
++				dprintk("%s - EXITING!\n", __FUNCTION__);
++				break;
++			}
++			cryptostats.cs_rets++;
++		}
++	}
++	CRYPTO_RETQ_UNLOCK();
++	complete_and_exit(&cryptoretproc_exited, 0);
++}
++
++
++#if 0 /* should put this into /proc or something */
++static void
++db_show_drivers(void)
++{
++	int hid;
++
++	db_printf("%12s %4s %4s %8s %2s %2s\n"
++		, "Device"
++		, "Ses"
++		, "Kops"
++		, "Flags"
++		, "QB"
++		, "KB"
++	);
++	for (hid = 0; hid < crypto_drivers_num; hid++) {
++		const struct cryptocap *cap = &crypto_drivers[hid];
++		if (cap->cc_dev == NULL)
++			continue;
++		db_printf("%-12s %4u %4u %08x %2u %2u\n"
++		    , device_get_nameunit(cap->cc_dev)
++		    , cap->cc_sessions
++		    , cap->cc_koperations
++		    , cap->cc_flags
++		    , cap->cc_qblocked
++		    , cap->cc_kqblocked
++		);
++	}
++}
++
++DB_SHOW_COMMAND(crypto, db_show_crypto)
++{
++	struct cryptop *crp;
++
++	db_show_drivers();
++	db_printf("\n");
++
++	db_printf("%4s %8s %4s %4s %4s %4s %8s %8s\n",
++	    "HID", "Caps", "Ilen", "Olen", "Etype", "Flags",
++	    "Desc", "Callback");
++	TAILQ_FOREACH(crp, &crp_q, crp_next) {
++		db_printf("%4u %08x %4u %4u %4u %04x %8p %8p\n"
++		    , (int) CRYPTO_SESID2HID(crp->crp_sid)
++		    , (int) CRYPTO_SESID2CAPS(crp->crp_sid)
++		    , crp->crp_ilen, crp->crp_olen
++		    , crp->crp_etype
++		    , crp->crp_flags
++		    , crp->crp_desc
++		    , crp->crp_callback
++		);
++	}
++	if (!TAILQ_EMPTY(&crp_ret_q)) {
++		db_printf("\n%4s %4s %4s %8s\n",
++		    "HID", "Etype", "Flags", "Callback");
++		TAILQ_FOREACH(crp, &crp_ret_q, crp_next) {
++			db_printf("%4u %4u %04x %8p\n"
++			    , (int) CRYPTO_SESID2HID(crp->crp_sid)
++			    , crp->crp_etype
++			    , crp->crp_flags
++			    , crp->crp_callback
++			);
++		}
++	}
++}
++
++DB_SHOW_COMMAND(kcrypto, db_show_kcrypto)
++{
++	struct cryptkop *krp;
++
++	db_show_drivers();
++	db_printf("\n");
++
++	db_printf("%4s %5s %4s %4s %8s %4s %8s\n",
++	    "Op", "Status", "#IP", "#OP", "CRID", "HID", "Callback");
++	TAILQ_FOREACH(krp, &crp_kq, krp_next) {
++		db_printf("%4u %5u %4u %4u %08x %4u %8p\n"
++		    , krp->krp_op
++		    , krp->krp_status
++		    , krp->krp_iparams, krp->krp_oparams
++		    , krp->krp_crid, krp->krp_hid
++		    , krp->krp_callback
++		);
++	}
++	if (!TAILQ_EMPTY(&crp_ret_q)) {
++		db_printf("%4s %5s %8s %4s %8s\n",
++		    "Op", "Status", "CRID", "HID", "Callback");
++		TAILQ_FOREACH(krp, &crp_ret_kq, krp_next) {
++			db_printf("%4u %5u %08x %4u %8p\n"
++			    , krp->krp_op
++			    , krp->krp_status
++			    , krp->krp_crid, krp->krp_hid
++			    , krp->krp_callback
++			);
++		}
++	}
++}
++#endif
++
++
++static int
++crypto_init(void)
++{
++	int error;
++
++	dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init);
++
++	if (crypto_initted)
++		return 0;
++	crypto_initted = 1;
++
++	atomic_set(&crypto_q_cnt, 0);
++
++	spin_lock_init(&crypto_drivers_lock);
++	spin_lock_init(&crypto_q_lock);
++	spin_lock_init(&crypto_ret_q_lock);
++
++	cryptop_zone = kmem_cache_create("cryptop", sizeof(struct cryptop),
++				       0, SLAB_HWCACHE_ALIGN, NULL
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
++				       , NULL
++#endif
++					);
++
++	cryptodesc_zone = kmem_cache_create("cryptodesc", sizeof(struct cryptodesc),
++				       0, SLAB_HWCACHE_ALIGN, NULL
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
++				       , NULL
++#endif
++					);
++
++	if (cryptodesc_zone == NULL || cryptop_zone == NULL) {
++		printk("crypto: crypto_init cannot setup crypto zones\n");
++		error = ENOMEM;
++		goto bad;
++	}
++
++	crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;
++	crypto_drivers = kmalloc(crypto_drivers_num * sizeof(struct cryptocap),
++			GFP_KERNEL);
++	if (crypto_drivers == NULL) {
++		printk("crypto: crypto_init cannot setup crypto drivers\n");
++		error = ENOMEM;
++		goto bad;
++	}
++
++	memset(crypto_drivers, 0, crypto_drivers_num * sizeof(struct cryptocap));
++
++	init_completion(&cryptoproc_exited);
++	init_completion(&cryptoretproc_exited);
++
++	cryptoproc = 0; /* to avoid race condition where proc runs first */
++	cryptoproc = kernel_thread(crypto_proc, NULL, CLONE_FS|CLONE_FILES);
++	if (cryptoproc < 0) {
++		error = cryptoproc;
++		printk("crypto: crypto_init cannot start crypto thread; error %d",
++			error);
++		goto bad;
++	}
++
++	cryptoretproc = 0; /* to avoid race condition where proc runs first */
++	cryptoretproc = kernel_thread(crypto_ret_proc, NULL, CLONE_FS|CLONE_FILES);
++	if (cryptoretproc < 0) {
++		error = cryptoretproc;
++		printk("crypto: crypto_init cannot start cryptoret thread; error %d",
++				error);
++		goto bad;
++	}
++
++	return 0;
++bad:
++	crypto_exit();
++	return error;
++}
++
++
++static void
++crypto_exit(void)
++{
++	pid_t p;
++	unsigned long d_flags;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	/*
++	 * Terminate any crypto threads.
++	 */
++
++	CRYPTO_DRIVER_LOCK();
++	p = cryptoproc;
++	cryptoproc = (pid_t) -1;
++	kill_proc(p, SIGTERM, 1);
++	wake_up_interruptible(&cryptoproc_wait);
++	CRYPTO_DRIVER_UNLOCK();
++
++	wait_for_completion(&cryptoproc_exited);
++
++	CRYPTO_DRIVER_LOCK();
++	p = cryptoretproc;
++	cryptoretproc = (pid_t) -1;
++	kill_proc(p, SIGTERM, 1);
++	wake_up_interruptible(&cryptoretproc_wait);
++	CRYPTO_DRIVER_UNLOCK();
++
++	wait_for_completion(&cryptoretproc_exited);
++
++	/* XXX flush queues??? */
++
++	/* 
++	 * Reclaim dynamically allocated resources.
++	 */
++	if (crypto_drivers != NULL)
++		kfree(crypto_drivers);
++
++	if (cryptodesc_zone != NULL)
++		kmem_cache_destroy(cryptodesc_zone);
++	if (cryptop_zone != NULL)
++		kmem_cache_destroy(cryptop_zone);
++}
++
++
++EXPORT_SYMBOL(crypto_newsession);
++EXPORT_SYMBOL(crypto_freesession);
++EXPORT_SYMBOL(crypto_get_driverid);
++EXPORT_SYMBOL(crypto_kregister);
++EXPORT_SYMBOL(crypto_register);
++EXPORT_SYMBOL(crypto_unregister);
++EXPORT_SYMBOL(crypto_unregister_all);
++EXPORT_SYMBOL(crypto_unblock);
++EXPORT_SYMBOL(crypto_dispatch);
++EXPORT_SYMBOL(crypto_kdispatch);
++EXPORT_SYMBOL(crypto_freereq);
++EXPORT_SYMBOL(crypto_getreq);
++EXPORT_SYMBOL(crypto_done);
++EXPORT_SYMBOL(crypto_kdone);
++EXPORT_SYMBOL(crypto_getfeat);
++EXPORT_SYMBOL(crypto_userasymcrypto);
++EXPORT_SYMBOL(crypto_getcaps);
++EXPORT_SYMBOL(crypto_find_driver);
++EXPORT_SYMBOL(crypto_find_device_byhid);
++
++module_init(crypto_init);
++module_exit(crypto_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("OCF (OpenBSD Cryptographic Framework)");
+diff -urN linux-2.6.23.16.old/crypto/ocf/cryptodev.c linux-2.6.23.16/crypto/ocf/cryptodev.c
+--- linux-2.6.23.16.old/crypto/ocf/cryptodev.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/cryptodev.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,1048 @@
++/*	$OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $	*/
++
++/*-
++ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ * The license and original author are listed below.
++ *
++ * Copyright (c) 2001 Theo de Raadt
++ * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *   derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
++ *
++__FBSDID("$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.34 2007/05/09 19:37:02 gnn Exp $");
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/types.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++#include <linux/list.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/unistd.h>
++#include <linux/module.h>
++#include <linux/wait.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/dcache.h>
++#include <linux/file.h>
++#include <linux/mount.h>
++#include <linux/miscdevice.h>
++#include <linux/version.h>
++#include <asm/uaccess.h>
++
++#include <cryptodev.h>
++#include <uio.h>
++
++extern asmlinkage long sys_dup(unsigned int fildes);
++
++#define debug cryptodev_debug
++int cryptodev_debug = 0;
++module_param(cryptodev_debug, int, 0644);
++MODULE_PARM_DESC(cryptodev_debug, "Enable cryptodev debug");
++
++struct csession_info {
++	u_int16_t	blocksize;
++	u_int16_t	minkey, maxkey;
++
++	u_int16_t	keysize;
++	/* u_int16_t	hashsize;  */
++	u_int16_t	authsize;
++	/* u_int16_t	ctxsize; */
++};
++
++struct csession {
++	struct list_head	list;
++	u_int64_t	sid;
++	u_int32_t	ses;
++
++	wait_queue_head_t waitq;
++
++	u_int32_t	cipher;
++
++	u_int32_t	mac;
++
++	caddr_t		key;
++	int		keylen;
++	u_char		tmp_iv[EALG_MAX_BLOCK_LEN];
++
++	caddr_t		mackey;
++	int		mackeylen;
++
++	struct csession_info info;
++
++	struct iovec	iovec;
++	struct uio	uio;
++	int		error;
++};
++
++struct fcrypt {
++	struct list_head	csessions;
++	int		sesn;
++};
++
++static struct csession *csefind(struct fcrypt *, u_int);
++static int csedelete(struct fcrypt *, struct csession *);
++static struct csession *cseadd(struct fcrypt *, struct csession *);
++static struct csession *csecreate(struct fcrypt *, u_int64_t,
++		struct cryptoini *crie, struct cryptoini *cria, struct csession_info *);
++static int csefree(struct csession *);
++
++static	int cryptodev_op(struct csession *, struct crypt_op *);
++static	int cryptodev_key(struct crypt_kop *);
++static	int cryptodev_find(struct crypt_find_op *);
++
++static int cryptodev_cb(void *);
++static int cryptodev_open(struct inode *inode, struct file *filp);
++
++/*
++ * Check a crypto identifier to see if it requested
++ * a valid crid and it's capabilities match.
++ */
++static int
++checkcrid(int crid)
++{
++	int hid = crid & ~(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
++	int typ = crid & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
++	int caps = 0;
++	
++	/* if the user hasn't selected a driver, then just call newsession */
++	if (hid == 0 && typ != 0)
++		return 0;
++
++	caps = crypto_getcaps(hid);
++
++	/* didn't find anything with capabilities */
++	if (caps == 0) {
++		dprintk("%s: hid=%x typ=%x not matched\n", __FUNCTION__, hid, typ);
++		return EINVAL;
++	}
++	
++	/* the user didn't specify SW or HW, so the driver is ok */
++	if (typ == 0)
++		return 0;
++
++	/* if the type specified didn't match */
++	if (typ != (caps & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE))) {
++		dprintk("%s: hid=%x typ=%x caps=%x not matched\n", __FUNCTION__,
++				hid, typ, caps);
++		return EINVAL;
++	}
++
++	return 0;
++}
++
++static int
++cryptodev_op(struct csession *cse, struct crypt_op *cop)
++{
++	struct cryptop *crp = NULL;
++	struct cryptodesc *crde = NULL, *crda = NULL;
++	int error = 0;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (cop->len > CRYPTO_MAX_DATA_LEN) {
++		dprintk("%s: %d > %d\n", __FUNCTION__, cop->len, CRYPTO_MAX_DATA_LEN);
++		return (E2BIG);
++	}
++
++	if (cse->info.blocksize && (cop->len % cse->info.blocksize) != 0) {
++		dprintk("%s: blocksize=%d len=%d\n", __FUNCTION__, cse->info.blocksize,
++				cop->len);
++		return (EINVAL);
++	}
++
++	cse->uio.uio_iov = &cse->iovec;
++	cse->uio.uio_iovcnt = 1;
++	cse->uio.uio_offset = 0;
++#if 0
++	cse->uio.uio_resid = cop->len;
++	cse->uio.uio_segflg = UIO_SYSSPACE;
++	cse->uio.uio_rw = UIO_WRITE;
++	cse->uio.uio_td = td;
++#endif
++	cse->uio.uio_iov[0].iov_len = cop->len;
++	if (cse->info.authsize)
++		cse->uio.uio_iov[0].iov_len += cse->info.authsize;
++	cse->uio.uio_iov[0].iov_base = kmalloc(cse->uio.uio_iov[0].iov_len,
++			GFP_KERNEL);
++
++	if (cse->uio.uio_iov[0].iov_base == NULL) {
++		dprintk("%s: iov_base kmalloc(%d) failed\n", __FUNCTION__,
++				cse->uio.uio_iov[0].iov_len);
++		return (ENOMEM);
++	}
++
++	crp = crypto_getreq((cse->info.blocksize != 0) + (cse->info.authsize != 0));
++	if (crp == NULL) {
++		dprintk("%s: ENOMEM\n", __FUNCTION__);
++		error = ENOMEM;
++		goto bail;
++	}
++
++	if (cse->info.authsize) {
++		crda = crp->crp_desc;
++		if (cse->info.blocksize)
++			crde = crda->crd_next;
++	} else {
++		if (cse->info.blocksize)
++			crde = crp->crp_desc;
++		else {
++			dprintk("%s: bad request\n", __FUNCTION__);
++			error = EINVAL;
++			goto bail;
++		}
++	}
++
++	if ((error = copy_from_user(cse->uio.uio_iov[0].iov_base, cop->src,
++					cop->len))) {
++		dprintk("%s: bad copy\n", __FUNCTION__);
++		goto bail;
++	}
++
++	if (crda) {
++		crda->crd_skip = 0;
++		crda->crd_len = cop->len;
++		crda->crd_inject = cop->len;
++
++		crda->crd_alg = cse->mac;
++		crda->crd_key = cse->mackey;
++		crda->crd_klen = cse->mackeylen * 8;
++	}
++
++	if (crde) {
++		if (cop->op == COP_ENCRYPT)
++			crde->crd_flags |= CRD_F_ENCRYPT;
++		else
++			crde->crd_flags &= ~CRD_F_ENCRYPT;
++		crde->crd_len = cop->len;
++		crde->crd_inject = 0;
++
++		crde->crd_alg = cse->cipher;
++		crde->crd_key = cse->key;
++		crde->crd_klen = cse->keylen * 8;
++	}
++
++	crp->crp_ilen = cse->uio.uio_iov[0].iov_len;
++	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
++		       | (cop->flags & COP_F_BATCH);
++	crp->crp_buf = (caddr_t)&cse->uio;
++	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
++	crp->crp_sid = cse->sid;
++	crp->crp_opaque = (void *)cse;
++
++	if (cop->iv) {
++		if (crde == NULL) {
++			error = EINVAL;
++			dprintk("%s no crde\n", __FUNCTION__);
++			goto bail;
++		}
++		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
++			error = EINVAL;
++			dprintk("%s arc4 with IV\n", __FUNCTION__);
++			goto bail;
++		}
++		if ((error = copy_from_user(cse->tmp_iv, cop->iv,
++						cse->info.blocksize))) {
++			dprintk("%s bad iv copy\n", __FUNCTION__);
++			goto bail;
++		}
++		memcpy(crde->crd_iv, cse->tmp_iv, cse->info.blocksize);
++		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
++		crde->crd_skip = 0;
++	} else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
++		crde->crd_skip = 0;
++	} else if (crde) {
++		crde->crd_flags |= CRD_F_IV_PRESENT;
++		crde->crd_skip = cse->info.blocksize;
++		crde->crd_len -= cse->info.blocksize;
++	}
++
++	if (cop->mac && crda == NULL) {
++		error = EINVAL;
++		dprintk("%s no crda\n", __FUNCTION__);
++		goto bail;
++	}
++
++	/*
++	 * Let the dispatch run unlocked, then, interlock against the
++	 * callback before checking if the operation completed and going
++	 * to sleep.  This insures drivers don't inherit our lock which
++	 * results in a lock order reversal between crypto_dispatch forced
++	 * entry and the crypto_done callback into us.
++	 */
++	error = crypto_dispatch(crp);
++	if (error == 0) {
++		dprintk("%s about to WAIT\n", __FUNCTION__);
++		/*
++		 * we really need to wait for driver to complete to maintain
++		 * state,  luckily interrupts will be remembered
++		 */
++		do {
++			error = wait_event_interruptible(crp->crp_waitq,
++					((crp->crp_flags & CRYPTO_F_DONE) != 0));
++			/*
++			 * we can't break out of this loop or we will leave behind
++			 * a huge mess,  however,  staying here means if your driver
++			 * is broken user applications can hang and not be killed.
++			 * The solution,  fix your driver :-)
++			 */
++			if (error) {
++				schedule();
++				error = 0;
++			}
++		} while ((crp->crp_flags & CRYPTO_F_DONE) == 0);
++		dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
++	}
++
++	if (crp->crp_etype != 0) {
++		error = crp->crp_etype;
++		dprintk("%s error in crp processing\n", __FUNCTION__);
++		goto bail;
++	}
++
++	if (cse->error) {
++		error = cse->error;
++		dprintk("%s error in cse processing\n", __FUNCTION__);
++		goto bail;
++	}
++
++	if (cop->dst && (error = copy_to_user(cop->dst,
++					cse->uio.uio_iov[0].iov_base, cop->len))) {
++		dprintk("%s bad dst copy\n", __FUNCTION__);
++		goto bail;
++	}
++
++	if (cop->mac &&
++			(error=copy_to_user(cop->mac,
++				(caddr_t)cse->uio.uio_iov[0].iov_base + cop->len,
++				cse->info.authsize))) {
++		dprintk("%s bad mac copy\n", __FUNCTION__);
++		goto bail;
++	}
++
++bail:
++	if (crp)
++		crypto_freereq(crp);
++	if (cse->uio.uio_iov[0].iov_base)
++		kfree(cse->uio.uio_iov[0].iov_base);
++
++	return (error);
++}
++
++static int
++cryptodev_cb(void *op)
++{
++	struct cryptop *crp = (struct cryptop *) op;
++	struct csession *cse = (struct csession *)crp->crp_opaque;
++	int error;
++
++	dprintk("%s()\n", __FUNCTION__);
++	error = crp->crp_etype;
++	if (error == EAGAIN) {
++		crp->crp_flags &= ~CRYPTO_F_DONE;
++#ifdef NOTYET
++		/*
++		 * DAVIDM I am fairly sure that we should turn this into a batch
++		 * request to stop bad karma/lockup, revisit
++		 */
++		crp->crp_flags |= CRYPTO_F_BATCH;
++#endif
++		return crypto_dispatch(crp);
++	}
++	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
++		cse->error = error;
++		wake_up_interruptible(&crp->crp_waitq);
++	}
++	return (0);
++}
++
++static int
++cryptodevkey_cb(void *op)
++{
++	struct cryptkop *krp = (struct cryptkop *) op;
++	dprintk("%s()\n", __FUNCTION__);
++	wake_up_interruptible(&krp->krp_waitq);
++	return (0);
++}
++
++static int
++cryptodev_key(struct crypt_kop *kop)
++{
++	struct cryptkop *krp = NULL;
++	int error = EINVAL;
++	int in, out, size, i;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
++		dprintk("%s params too big\n", __FUNCTION__);
++		return (EFBIG);
++	}
++
++	in = kop->crk_iparams;
++	out = kop->crk_oparams;
++	switch (kop->crk_op) {
++	case CRK_MOD_EXP:
++		if (in == 3 && out == 1)
++			break;
++		return (EINVAL);
++	case CRK_MOD_EXP_CRT:
++		if (in == 6 && out == 1)
++			break;
++		return (EINVAL);
++	case CRK_DSA_SIGN:
++		if (in == 5 && out == 2)
++			break;
++		return (EINVAL);
++	case CRK_DSA_VERIFY:
++		if (in == 7 && out == 0)
++			break;
++		return (EINVAL);
++	case CRK_DH_COMPUTE_KEY:
++		if (in == 3 && out == 1)
++			break;
++		return (EINVAL);
++	default:
++		return (EINVAL);
++	}
++
++	krp = (struct cryptkop *)kmalloc(sizeof *krp, GFP_KERNEL);
++	if (!krp)
++		return (ENOMEM);
++	bzero(krp, sizeof *krp);
++	krp->krp_op = kop->crk_op;
++	krp->krp_status = kop->crk_status;
++	krp->krp_iparams = kop->crk_iparams;
++	krp->krp_oparams = kop->crk_oparams;
++	krp->krp_crid = kop->crk_crid;
++	krp->krp_status = 0;
++	krp->krp_flags = CRYPTO_KF_CBIMM;
++	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
++	init_waitqueue_head(&krp->krp_waitq);
++
++	for (i = 0; i < CRK_MAXPARAM; i++)
++		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
++	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
++		size = (krp->krp_param[i].crp_nbits + 7) / 8;
++		if (size == 0)
++			continue;
++		krp->krp_param[i].crp_p = (caddr_t) kmalloc(size, GFP_KERNEL);
++		if (i >= krp->krp_iparams)
++			continue;
++		error = copy_from_user(krp->krp_param[i].crp_p,
++				kop->crk_param[i].crp_p, size);
++		if (error)
++			goto fail;
++	}
++
++	error = crypto_kdispatch(krp);
++	if (error)
++		goto fail;
++
++	do {
++		error = wait_event_interruptible(krp->krp_waitq,
++				((krp->krp_flags & CRYPTO_KF_DONE) != 0));
++		/*
++		 * we can't break out of this loop or we will leave behind
++		 * a huge mess,  however,  staying here means if your driver
++		 * is broken user applications can hang and not be killed.
++		 * The solution,  fix your driver :-)
++		 */
++		if (error) {
++			schedule();
++			error = 0;
++		}
++	} while ((krp->krp_flags & CRYPTO_KF_DONE) == 0);
++
++	dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
++	
++	kop->crk_crid = krp->krp_crid;		/* device that did the work */
++	if (krp->krp_status != 0) {
++		error = krp->krp_status;
++		goto fail;
++	}
++
++	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
++		size = (krp->krp_param[i].crp_nbits + 7) / 8;
++		if (size == 0)
++			continue;
++		error = copy_to_user(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p,
++				size);
++		if (error)
++			goto fail;
++	}
++
++fail:
++	if (krp) {
++		kop->crk_status = krp->krp_status;
++		for (i = 0; i < CRK_MAXPARAM; i++) {
++			if (krp->krp_param[i].crp_p)
++				kfree(krp->krp_param[i].crp_p);
++		}
++		kfree(krp);
++	}
++	return (error);
++}
++
++static int
++cryptodev_find(struct crypt_find_op *find)
++{
++	device_t dev;
++
++	if (find->crid != -1) {
++		dev = crypto_find_device_byhid(find->crid);
++		if (dev == NULL)
++			return (ENOENT);
++		strlcpy(find->name, device_get_nameunit(dev),
++		    sizeof(find->name));
++	} else {
++		find->crid = crypto_find_driver(find->name);
++		if (find->crid == -1)
++			return (ENOENT);
++	}
++	return (0);
++}
++
++static struct csession *
++csefind(struct fcrypt *fcr, u_int ses)
++{
++	struct csession *cse;
++
++	dprintk("%s()\n", __FUNCTION__);
++	list_for_each_entry(cse, &fcr->csessions, list)
++		if (cse->ses == ses)
++			return (cse);
++	return (NULL);
++}
++
++static int
++csedelete(struct fcrypt *fcr, struct csession *cse_del)
++{
++	struct csession *cse;
++
++	dprintk("%s()\n", __FUNCTION__);
++	list_for_each_entry(cse, &fcr->csessions, list) {
++		if (cse == cse_del) {
++			list_del(&cse->list);
++			return (1);
++		}
++	}
++	return (0);
++}
++	
++static struct csession *
++cseadd(struct fcrypt *fcr, struct csession *cse)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	list_add_tail(&cse->list, &fcr->csessions);
++	cse->ses = fcr->sesn++;
++	return (cse);
++}
++
++static struct csession *
++csecreate(struct fcrypt *fcr, u_int64_t sid, struct cryptoini *crie,
++	struct cryptoini *cria, struct csession_info *info)
++{
++	struct csession *cse;
++
++	dprintk("%s()\n", __FUNCTION__);
++	cse = (struct csession *) kmalloc(sizeof(struct csession), GFP_KERNEL);
++	if (cse == NULL)
++		return NULL;
++	memset(cse, 0, sizeof(struct csession));
++
++	INIT_LIST_HEAD(&cse->list);
++	init_waitqueue_head(&cse->waitq);
++
++	cse->key = crie->cri_key;
++	cse->keylen = crie->cri_klen/8;
++	cse->mackey = cria->cri_key;
++	cse->mackeylen = cria->cri_klen/8;
++	cse->sid = sid;
++	cse->cipher = crie->cri_alg;
++	cse->mac = cria->cri_alg;
++	cse->info = *info;
++	cseadd(fcr, cse);
++	return (cse);
++}
++
++static int
++csefree(struct csession *cse)
++{
++	int error;
++
++	dprintk("%s()\n", __FUNCTION__);
++	error = crypto_freesession(cse->sid);
++	if (cse->key)
++		kfree(cse->key);
++	if (cse->mackey)
++		kfree(cse->mackey);
++	kfree(cse);
++	return(error);
++}
++
++static int
++cryptodev_ioctl(
++	struct inode *inode,
++	struct file *filp,
++	unsigned int cmd,
++	unsigned long arg)
++{
++	struct cryptoini cria, crie;
++	struct fcrypt *fcr = filp->private_data;
++	struct csession *cse;
++	struct csession_info info;
++	struct session2_op sop;
++	struct crypt_op cop;
++	struct crypt_kop kop;
++	struct crypt_find_op fop;
++	u_int64_t sid;
++	u_int32_t ses;
++	int feat, fd, error = 0, crid;
++	mm_segment_t fs;
++
++	dprintk("%s(cmd=%x arg=%lx)\n", __FUNCTION__, cmd, arg);
++
++	switch (cmd) {
++
++	case CRIOGET: {
++		dprintk("%s(CRIOGET)\n", __FUNCTION__);
++		fs = get_fs();
++		set_fs(get_ds());
++		for (fd = 0; fd < files_fdtable(current->files)->max_fds; fd++)
++			if (files_fdtable(current->files)->fd[fd] == filp)
++				break;
++		fd = sys_dup(fd);
++		set_fs(fs);
++		put_user(fd, (int *) arg);
++		return IS_ERR_VALUE(fd) ? fd : 0;
++		}
++
++#define	CIOCGSESSSTR	(cmd == CIOCGSESSION ? "CIOCGSESSION" : "CIOCGSESSION2")
++	case CIOCGSESSION:
++	case CIOCGSESSION2:
++		dprintk("%s(%s)\n", __FUNCTION__, CIOCGSESSSTR);
++		memset(&crie, 0, sizeof(crie));
++		memset(&cria, 0, sizeof(cria));
++		memset(&info, 0, sizeof(info));
++		memset(&sop, 0, sizeof(sop));
++
++		if (copy_from_user(&sop, (void*)arg, (cmd == CIOCGSESSION) ?
++					sizeof(struct session_op) : sizeof(sop))) {
++			dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
++			error = EFAULT;
++			goto bail;
++		}
++
++		switch (sop.cipher) {
++		case 0:
++			dprintk("%s(%s) - no cipher\n", __FUNCTION__, CIOCGSESSSTR);
++			break;
++		case CRYPTO_NULL_CBC:
++			info.blocksize = NULL_BLOCK_LEN;
++			info.minkey = NULL_MIN_KEY_LEN;
++			info.maxkey = NULL_MAX_KEY_LEN;
++			break;
++		case CRYPTO_DES_CBC:
++			info.blocksize = DES_BLOCK_LEN;
++			info.minkey = DES_MIN_KEY_LEN;
++			info.maxkey = DES_MAX_KEY_LEN;
++			break;
++		case CRYPTO_3DES_CBC:
++			info.blocksize = DES3_BLOCK_LEN;
++			info.minkey = DES3_MIN_KEY_LEN;
++			info.maxkey = DES3_MAX_KEY_LEN;
++			break;
++		case CRYPTO_BLF_CBC:
++			info.blocksize = BLOWFISH_BLOCK_LEN;
++			info.minkey = BLOWFISH_MIN_KEY_LEN;
++			info.maxkey = BLOWFISH_MAX_KEY_LEN;
++			break;
++		case CRYPTO_CAST_CBC:
++			info.blocksize = CAST128_BLOCK_LEN;
++			info.minkey = CAST128_MIN_KEY_LEN;
++			info.maxkey = CAST128_MAX_KEY_LEN;
++			break;
++		case CRYPTO_SKIPJACK_CBC:
++			info.blocksize = SKIPJACK_BLOCK_LEN;
++			info.minkey = SKIPJACK_MIN_KEY_LEN;
++			info.maxkey = SKIPJACK_MAX_KEY_LEN;
++			break;
++		case CRYPTO_AES_CBC:
++			info.blocksize = AES_BLOCK_LEN;
++			info.minkey = AES_MIN_KEY_LEN;
++			info.maxkey = AES_MAX_KEY_LEN;
++			break;
++		case CRYPTO_ARC4:
++			info.blocksize = ARC4_BLOCK_LEN;
++			info.minkey = ARC4_MIN_KEY_LEN;
++			info.maxkey = ARC4_MAX_KEY_LEN;
++			break;
++		case CRYPTO_CAMELLIA_CBC:
++			info.blocksize = CAMELLIA_BLOCK_LEN;
++			info.minkey = CAMELLIA_MIN_KEY_LEN;
++			info.maxkey = CAMELLIA_MAX_KEY_LEN;
++			break;
++		default:
++			dprintk("%s(%s) - bad cipher\n", __FUNCTION__, CIOCGSESSSTR);
++			error = EINVAL;
++			goto bail;
++		}
++
++		switch (sop.mac) {
++		case 0:
++			dprintk("%s(%s) - no mac\n", __FUNCTION__, CIOCGSESSSTR);
++			break;
++		case CRYPTO_NULL_HMAC:
++			info.authsize = NULL_HASH_LEN;
++			break;
++		case CRYPTO_MD5:
++			info.authsize = MD5_HASH_LEN;
++			break;
++		case CRYPTO_SHA1:
++			info.authsize = SHA1_HASH_LEN;
++			break;
++		case CRYPTO_SHA2_256:
++			info.authsize = SHA2_256_HASH_LEN;
++			break;
++		case CRYPTO_SHA2_384:
++			info.authsize = SHA2_384_HASH_LEN;
++  			break;
++		case CRYPTO_SHA2_512:
++			info.authsize = SHA2_512_HASH_LEN;
++			break;
++		case CRYPTO_RIPEMD160:
++			info.authsize = RIPEMD160_HASH_LEN;
++			break;
++		case CRYPTO_MD5_HMAC:
++			info.authsize = MD5_HASH_LEN;
++			break;
++		case CRYPTO_SHA1_HMAC:
++			info.authsize = SHA1_HASH_LEN;
++			break;
++		case CRYPTO_SHA2_256_HMAC:
++			info.authsize = SHA2_256_HASH_LEN;
++			break;
++		case CRYPTO_SHA2_384_HMAC:
++			info.authsize = SHA2_384_HASH_LEN;
++  			break;
++		case CRYPTO_SHA2_512_HMAC:
++			info.authsize = SHA2_512_HASH_LEN;
++			break;
++		case CRYPTO_RIPEMD160_HMAC:
++			info.authsize = RIPEMD160_HASH_LEN;
++			break;
++		default:
++			dprintk("%s(%s) - bad mac\n", __FUNCTION__, CIOCGSESSSTR);
++			error = EINVAL;
++			goto bail;
++		}
++
++		if (info.blocksize) {
++			crie.cri_alg = sop.cipher;
++			crie.cri_klen = sop.keylen * 8;
++			if ((info.maxkey && sop.keylen > info.maxkey) ||
++				   	sop.keylen < info.minkey) {
++				dprintk("%s(%s) - bad key\n", __FUNCTION__, CIOCGSESSSTR);
++				error = EINVAL;
++				goto bail;
++			}
++
++			crie.cri_key = (u_int8_t *) kmalloc(crie.cri_klen/8+1, GFP_KERNEL);
++			if (copy_from_user(crie.cri_key, sop.key,
++							crie.cri_klen/8)) {
++				dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
++				error = EFAULT;
++				goto bail;
++			}
++			if (info.authsize)
++				crie.cri_next = &cria;
++		}
++
++		if (info.authsize) {
++			cria.cri_alg = sop.mac;
++			cria.cri_klen = sop.mackeylen * 8;
++			if ((info.maxkey && sop.mackeylen > info.maxkey) ||
++					sop.keylen < info.minkey) {
++				dprintk("%s(%s) - mackeylen %d\n", __FUNCTION__, CIOCGSESSSTR,
++						sop.mackeylen);
++				error = EINVAL;
++				goto bail;
++			}
++
++			if (cria.cri_klen) {
++				cria.cri_key = (u_int8_t *) kmalloc(cria.cri_klen/8,GFP_KERNEL);
++				if (copy_from_user(cria.cri_key, sop.mackey,
++								cria.cri_klen / 8)) {
++					dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
++					error = EFAULT;
++					goto bail;
++				}
++			}
++		}
++
++		/* NB: CIOGSESSION2 has the crid */
++		if (cmd == CIOCGSESSION2) {
++			crid = sop.crid;
++			error = checkcrid(crid);
++			if (error) {
++				dprintk("%s(%s) - checkcrid %x\n", __FUNCTION__,
++						CIOCGSESSSTR, error);
++				goto bail;
++			}
++		} else {
++			/* allow either HW or SW to be used */
++			crid = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
++		}
++		error = crypto_newsession(&sid, (info.blocksize ? &crie : &cria), crid);
++		if (error) {
++			dprintk("%s(%s) - newsession %d\n",__FUNCTION__,CIOCGSESSSTR,error);
++			goto bail;
++		}
++
++		cse = csecreate(fcr, sid, &crie, &cria, &info);
++		if (cse == NULL) {
++			crypto_freesession(sid);
++			error = EINVAL;
++			dprintk("%s(%s) - csecreate failed\n", __FUNCTION__, CIOCGSESSSTR);
++			goto bail;
++		}
++		sop.ses = cse->ses;
++
++		if (cmd == CIOCGSESSION2) {
++			/* return hardware/driver id */
++			sop.crid = CRYPTO_SESID2HID(cse->sid);
++		}
++
++		if (copy_to_user((void*)arg, &sop, (cmd == CIOCGSESSION) ?
++					sizeof(struct session_op) : sizeof(sop))) {
++			dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
++			error = EFAULT;
++		}
++bail:
++		if (error) {
++			dprintk("%s(%s) - bail %d\n", __FUNCTION__, CIOCGSESSSTR, error);
++			if (crie.cri_key)
++				kfree(crie.cri_key);
++			if (cria.cri_key)
++				kfree(cria.cri_key);
++		}
++		break;
++	case CIOCFSESSION:
++		dprintk("%s(CIOCFSESSION)\n", __FUNCTION__);
++		get_user(ses, (uint32_t*)arg);
++		cse = csefind(fcr, ses);
++		if (cse == NULL) {
++			error = EINVAL;
++			dprintk("%s(CIOCFSESSION) - Fail %d\n", __FUNCTION__, error);
++			break;
++		}
++		csedelete(fcr, cse);
++		error = csefree(cse);
++		break;
++	case CIOCCRYPT:
++		dprintk("%s(CIOCCRYPT)\n", __FUNCTION__);
++		if(copy_from_user(&cop, (void*)arg, sizeof(cop))) {
++			dprintk("%s(CIOCCRYPT) - bad copy\n", __FUNCTION__);
++			error = EFAULT;
++			goto bail;
++		}
++		cse = csefind(fcr, cop.ses);
++		if (cse == NULL) {
++			error = EINVAL;
++			dprintk("%s(CIOCCRYPT) - Fail %d\n", __FUNCTION__, error);
++			break;
++		}
++		error = cryptodev_op(cse, &cop);
++		if(copy_to_user((void*)arg, &cop, sizeof(cop))) {
++			dprintk("%s(CIOCCRYPT) - bad return copy\n", __FUNCTION__);
++			error = EFAULT;
++			goto bail;
++		}
++		break;
++	case CIOCKEY:
++	case CIOCKEY2:
++		dprintk("%s(CIOCKEY)\n", __FUNCTION__);
++		if (!crypto_userasymcrypto)
++			return (EPERM);		/* XXX compat? */
++		if(copy_from_user(&kop, (void*)arg, sizeof(kop))) {
++			dprintk("%s(CIOCKEY) - bad copy\n", __FUNCTION__);
++			error = EFAULT;
++			goto bail;
++		}
++		if (cmd == CIOCKEY) {
++			/* NB: crypto core enforces s/w driver use */
++			kop.crk_crid =
++			    CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
++		}
++		error = cryptodev_key(&kop);
++		if(copy_to_user((void*)arg, &kop, sizeof(kop))) {
++			dprintk("%s(CIOCGKEY) - bad return copy\n", __FUNCTION__);
++			error = EFAULT;
++			goto bail;
++		}
++		break;
++	case CIOCASYMFEAT:
++		dprintk("%s(CIOCASYMFEAT)\n", __FUNCTION__);
++		if (!crypto_userasymcrypto) {
++			/*
++			 * NB: if user asym crypto operations are
++			 * not permitted return "no algorithms"
++			 * so well-behaved applications will just
++			 * fallback to doing them in software.
++			 */
++			feat = 0;
++		} else
++			error = crypto_getfeat(&feat);
++		if (!error) {
++		  error = copy_to_user((void*)arg, &feat, sizeof(feat));
++		}
++		break;
++	case CIOCFINDDEV:
++		if (copy_from_user(&fop, (void*)arg, sizeof(fop))) {
++			dprintk("%s(CIOCFINDDEV) - bad copy\n", __FUNCTION__);
++			error = EFAULT;
++			goto bail;
++		}
++		error = cryptodev_find(&fop);
++		if (copy_to_user((void*)arg, &fop, sizeof(fop))) {
++			dprintk("%s(CIOCFINDDEV) - bad return copy\n", __FUNCTION__);
++			error = EFAULT;
++			goto bail;
++		}
++		break;
++	default:
++		dprintk("%s(unknown ioctl 0x%x)\n", __FUNCTION__, cmd);
++		error = EINVAL;
++		break;
++	}
++	return(-error);
++}
++
++#ifdef HAVE_UNLOCKED_IOCTL
++static long
++cryptodev_unlocked_ioctl(
++	struct file *filp,
++	unsigned int cmd,
++	unsigned long arg)
++{
++	return cryptodev_ioctl(NULL, filp, cmd, arg);
++}
++#endif
++
++static int
++cryptodev_open(struct inode *inode, struct file *filp)
++{
++	struct fcrypt *fcr;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (filp->private_data) {
++		printk("cryptodev: Private data already exists !\n");
++		return(0);
++	}
++
++	fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
++	if (!fcr) {
++		dprintk("%s() - malloc failed\n", __FUNCTION__);
++		return(-ENOMEM);
++	}
++	memset(fcr, 0, sizeof(*fcr));
++
++	INIT_LIST_HEAD(&fcr->csessions);
++	filp->private_data = fcr;
++	return(0);
++}
++
++static int
++cryptodev_release(struct inode *inode, struct file *filp)
++{
++	struct fcrypt *fcr = filp->private_data;
++	struct csession *cse, *tmp;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (!filp) {
++		printk("cryptodev: No private data on release\n");
++		return(0);
++	}
++
++	list_for_each_entry_safe(cse, tmp, &fcr->csessions, list) {
++		list_del(&cse->list);
++		(void)csefree(cse);
++	}
++	filp->private_data = NULL;
++	kfree(fcr);
++	return(0);
++}
++
++static struct file_operations cryptodev_fops = {
++	.owner = THIS_MODULE,
++	.open = cryptodev_open,
++	.release = cryptodev_release,
++	.ioctl = cryptodev_ioctl,
++#ifdef HAVE_UNLOCKED_IOCTL
++	.unlocked_ioctl = cryptodev_unlocked_ioctl,
++#endif
++};
++
++static struct miscdevice cryptodev = {
++	.minor = CRYPTODEV_MINOR,
++	.name = "crypto",
++	.fops = &cryptodev_fops,
++};
++
++static int __init
++cryptodev_init(void)
++{
++	int rc;
++
++	dprintk("%s(%p)\n", __FUNCTION__, cryptodev_init);
++	rc = misc_register(&cryptodev);
++	if (rc) {
++		printk(KERN_ERR "cryptodev: registration of /dev/crypto failed\n");
++		return(rc);
++	}
++
++	return(0);
++}
++
++static void __exit
++cryptodev_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	misc_deregister(&cryptodev);
++}
++
++module_init(cryptodev_init);
++module_exit(cryptodev_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("Cryptodev (user interface to OCF)");
+diff -urN linux-2.6.23.16.old/crypto/ocf/cryptodev.h linux-2.6.23.16/crypto/ocf/cryptodev.h
+--- linux-2.6.23.16.old/crypto/ocf/cryptodev.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/cryptodev.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,478 @@
++/*	$FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.25 2007/05/09 19:37:02 gnn Exp $	*/
++/*	$OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $	*/
++
++/*-
++ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ * The license and original author are listed below.
++ *
++ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
++ * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
++ *
++ * This code was written by Angelos D. Keromytis in Athens, Greece, in
++ * February 2000. Network Security Technologies Inc. (NSTI) kindly
++ * supported the development of this code.
++ *
++ * Copyright (c) 2000 Angelos D. Keromytis
++ *
++ * Permission to use, copy, and modify this software with or without fee
++ * is hereby granted, provided that this entire notice is included in
++ * all source code copies of any software which is or includes a copy or
++ * modification of this software.
++ *
++ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
++ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
++ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
++ * PURPOSE.
++ *
++ * Copyright (c) 2001 Theo de Raadt
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *   derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
++ *
++ */
++
++#ifndef _CRYPTO_CRYPTO_H_
++#define _CRYPTO_CRYPTO_H_
++
++/* Some initial values */
++#define CRYPTO_DRIVERS_INITIAL	4
++#define CRYPTO_SW_SESSIONS	32
++
++/* Hash values */
++#define NULL_HASH_LEN		0
++#define MD5_HASH_LEN		16
++#define SHA1_HASH_LEN		20
++#define RIPEMD160_HASH_LEN	20
++#define SHA2_256_HASH_LEN	32
++#define SHA2_384_HASH_LEN	48
++#define SHA2_512_HASH_LEN	64
++#define MD5_KPDK_HASH_LEN	16
++#define SHA1_KPDK_HASH_LEN	20
++/* Maximum hash algorithm result length */
++#define HASH_MAX_LEN		SHA2_512_HASH_LEN /* Keep this updated */
++
++/* HMAC values */
++#define NULL_HMAC_BLOCK_LEN			1
++#define MD5_HMAC_BLOCK_LEN			64
++#define SHA1_HMAC_BLOCK_LEN			64
++#define RIPEMD160_HMAC_BLOCK_LEN	64
++#define SHA2_256_HMAC_BLOCK_LEN		64
++#define SHA2_384_HMAC_BLOCK_LEN		128
++#define SHA2_512_HMAC_BLOCK_LEN		128
++/* Maximum HMAC block length */
++#define HMAC_MAX_BLOCK_LEN		SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */
++#define HMAC_IPAD_VAL			0x36
++#define HMAC_OPAD_VAL			0x5C
++
++/* Encryption algorithm block sizes */
++#define NULL_BLOCK_LEN			1
++#define DES_BLOCK_LEN			8
++#define DES3_BLOCK_LEN			8
++#define BLOWFISH_BLOCK_LEN		8
++#define SKIPJACK_BLOCK_LEN		8
++#define CAST128_BLOCK_LEN		8
++#define RIJNDAEL128_BLOCK_LEN	16
++#define AES_BLOCK_LEN			RIJNDAEL128_BLOCK_LEN
++#define CAMELLIA_BLOCK_LEN		16
++#define ARC4_BLOCK_LEN			1
++#define EALG_MAX_BLOCK_LEN		AES_BLOCK_LEN /* Keep this updated */
++
++/* Encryption algorithm min and max key sizes */
++#define NULL_MIN_KEY_LEN		0
++#define NULL_MAX_KEY_LEN		0
++#define DES_MIN_KEY_LEN			8
++#define DES_MAX_KEY_LEN			8
++#define DES3_MIN_KEY_LEN		24
++#define DES3_MAX_KEY_LEN		24
++#define BLOWFISH_MIN_KEY_LEN	4
++#define BLOWFISH_MAX_KEY_LEN	56
++#define SKIPJACK_MIN_KEY_LEN	10
++#define SKIPJACK_MAX_KEY_LEN	10
++#define CAST128_MIN_KEY_LEN		5
++#define CAST128_MAX_KEY_LEN		16
++#define RIJNDAEL128_MIN_KEY_LEN	16
++#define RIJNDAEL128_MAX_KEY_LEN	32
++#define AES_MIN_KEY_LEN			RIJNDAEL128_MIN_KEY_LEN
++#define AES_MAX_KEY_LEN			RIJNDAEL128_MAX_KEY_LEN
++#define CAMELLIA_MIN_KEY_LEN	16
++#define CAMELLIA_MAX_KEY_LEN	32
++#define ARC4_MIN_KEY_LEN		1
++#define ARC4_MAX_KEY_LEN		256
++
++/* Max size of data that can be processed */
++#define CRYPTO_MAX_DATA_LEN		64*1024 - 1
++
++#define CRYPTO_ALGORITHM_MIN	1
++#define CRYPTO_DES_CBC			1
++#define CRYPTO_3DES_CBC			2
++#define CRYPTO_BLF_CBC			3
++#define CRYPTO_CAST_CBC			4
++#define CRYPTO_SKIPJACK_CBC		5
++#define CRYPTO_MD5_HMAC			6
++#define CRYPTO_SHA1_HMAC		7
++#define CRYPTO_RIPEMD160_HMAC	8
++#define CRYPTO_MD5_KPDK			9
++#define CRYPTO_SHA1_KPDK		10
++#define CRYPTO_RIJNDAEL128_CBC	11 /* 128 bit blocksize */
++#define CRYPTO_AES_CBC			11 /* 128 bit blocksize -- the same as above */
++#define CRYPTO_ARC4				12
++#define CRYPTO_MD5				13
++#define CRYPTO_SHA1				14
++#define CRYPTO_NULL_HMAC		15
++#define CRYPTO_NULL_CBC			16
++#define CRYPTO_DEFLATE_COMP		17 /* Deflate compression algorithm */
++#define CRYPTO_SHA2_256_HMAC	18
++#define CRYPTO_SHA2_384_HMAC	19
++#define CRYPTO_SHA2_512_HMAC	20
++#define CRYPTO_CAMELLIA_CBC		21
++#define CRYPTO_SHA2_256			22
++#define CRYPTO_SHA2_384			23
++#define CRYPTO_SHA2_512			24
++#define CRYPTO_RIPEMD160		25
++#define CRYPTO_ALGORITHM_MAX	25 /* Keep updated - see below */
++
++/* Algorithm flags */
++#define CRYPTO_ALG_FLAG_SUPPORTED	0x01 /* Algorithm is supported */
++#define CRYPTO_ALG_FLAG_RNG_ENABLE	0x02 /* Has HW RNG for DH/DSA */
++#define CRYPTO_ALG_FLAG_DSA_SHA		0x04 /* Can do SHA on msg */
++
++/*
++ * Crypto driver/device flags.  They can set in the crid
++ * parameter when creating a session or submitting a key
++ * op to affect the device/driver assigned.  If neither
++ * of these are specified then the crid is assumed to hold
++ * the driver id of an existing (and suitable) device that
++ * must be used to satisfy the request.
++ */
++#define CRYPTO_FLAG_HARDWARE	0x01000000	/* hardware accelerated */
++#define CRYPTO_FLAG_SOFTWARE	0x02000000	/* software implementation */
++
++/* NB: deprecated */
++struct session_op {
++	u_int32_t	cipher;		/* ie. CRYPTO_DES_CBC */
++	u_int32_t	mac;		/* ie. CRYPTO_MD5_HMAC */
++
++	u_int32_t	keylen;		/* cipher key */
++	caddr_t		key;
++	int		mackeylen;	/* mac key */
++	caddr_t		mackey;
++
++  	u_int32_t	ses;		/* returns: session # */ 
++};
++
++struct session2_op {
++	u_int32_t	cipher;		/* ie. CRYPTO_DES_CBC */
++	u_int32_t	mac;		/* ie. CRYPTO_MD5_HMAC */
++
++	u_int32_t	keylen;		/* cipher key */
++	caddr_t		key;
++	int		mackeylen;	/* mac key */
++	caddr_t		mackey;
++
++  	u_int32_t	ses;		/* returns: session # */ 
++	int		crid;		/* driver id + flags (rw) */
++	int		pad[4];		/* for future expansion */
++};
++
++struct crypt_op {
++	u_int32_t	ses;
++	u_int16_t	op;		/* i.e. COP_ENCRYPT */
++#define COP_NONE	0
++#define COP_ENCRYPT	1
++#define COP_DECRYPT	2
++	u_int16_t	flags;
++#define	COP_F_BATCH	0x0008		/* Batch op if possible */
++	u_int		len;
++	caddr_t		src, dst;	/* become iov[] inside kernel */
++	caddr_t		mac;		/* must be big enough for chosen MAC */
++	caddr_t		iv;
++};
++
++/*
++ * Parameters for looking up a crypto driver/device by
++ * device name or by id.  The latter are returned for
++ * created sessions (crid) and completed key operations.
++ */
++struct crypt_find_op {
++	int		crid;		/* driver id + flags */
++	char		name[32];	/* device/driver name */
++};
++
++/* bignum parameter, in packed bytes, ... */
++struct crparam {
++	caddr_t		crp_p;
++	u_int		crp_nbits;
++};
++
++#define CRK_MAXPARAM	8
++
++struct crypt_kop {
++	u_int		crk_op;		/* ie. CRK_MOD_EXP or other */
++	u_int		crk_status;	/* return status */
++	u_short		crk_iparams;	/* # of input parameters */
++	u_short		crk_oparams;	/* # of output parameters */
++	u_int		crk_crid;	/* NB: only used by CIOCKEY2 (rw) */
++	struct crparam	crk_param[CRK_MAXPARAM];
++};
++#define CRK_ALGORITM_MIN	0
++#define CRK_MOD_EXP		0
++#define CRK_MOD_EXP_CRT		1
++#define CRK_DSA_SIGN		2
++#define CRK_DSA_VERIFY		3
++#define CRK_DH_COMPUTE_KEY	4
++#define CRK_ALGORITHM_MAX	4 /* Keep updated - see below */
++
++#define CRF_MOD_EXP		(1 << CRK_MOD_EXP)
++#define CRF_MOD_EXP_CRT		(1 << CRK_MOD_EXP_CRT)
++#define CRF_DSA_SIGN		(1 << CRK_DSA_SIGN)
++#define CRF_DSA_VERIFY		(1 << CRK_DSA_VERIFY)
++#define CRF_DH_COMPUTE_KEY	(1 << CRK_DH_COMPUTE_KEY)
++
++/*
++ * done against open of /dev/crypto, to get a cloned descriptor.
++ * Please use F_SETFD against the cloned descriptor.
++ */
++#define CRIOGET		_IOWR('c', 100, u_int32_t)
++#define CRIOASYMFEAT	CIOCASYMFEAT
++#define CRIOFINDDEV	CIOCFINDDEV
++
++/* the following are done against the cloned descriptor */
++#define CIOCGSESSION	_IOWR('c', 101, struct session_op)
++#define CIOCFSESSION	_IOW('c', 102, u_int32_t)
++#define CIOCCRYPT	_IOWR('c', 103, struct crypt_op)
++#define CIOCKEY		_IOWR('c', 104, struct crypt_kop)
++#define CIOCASYMFEAT	_IOR('c', 105, u_int32_t)
++#define CIOCGSESSION2	_IOWR('c', 106, struct session2_op)
++#define CIOCKEY2	_IOWR('c', 107, struct crypt_kop)
++#define CIOCFINDDEV	_IOWR('c', 108, struct crypt_find_op)
++
++struct cryptotstat {
++	struct timespec	acc;		/* total accumulated time */
++	struct timespec	min;		/* min time */
++	struct timespec	max;		/* max time */
++	u_int32_t	count;		/* number of observations */
++};
++
++struct cryptostats {
++	u_int32_t	cs_ops;		/* symmetric crypto ops submitted */
++	u_int32_t	cs_errs;	/* symmetric crypto ops that failed */
++	u_int32_t	cs_kops;	/* asymetric/key ops submitted */
++	u_int32_t	cs_kerrs;	/* asymetric/key ops that failed */
++	u_int32_t	cs_intrs;	/* crypto swi thread activations */
++	u_int32_t	cs_rets;	/* crypto return thread activations */
++	u_int32_t	cs_blocks;	/* symmetric op driver block */
++	u_int32_t	cs_kblocks;	/* symmetric op driver block */
++	/*
++	 * When CRYPTO_TIMING is defined at compile time and the
++	 * sysctl debug.crypto is set to 1, the crypto system will
++	 * accumulate statistics about how long it takes to process
++	 * crypto requests at various points during processing.
++	 */
++	struct cryptotstat cs_invoke;	/* crypto_dipsatch -> crypto_invoke */
++	struct cryptotstat cs_done;	/* crypto_invoke -> crypto_done */
++	struct cryptotstat cs_cb;	/* crypto_done -> callback */
++	struct cryptotstat cs_finis;	/* callback -> callback return */
++
++	u_int32_t	cs_drops;		/* crypto ops dropped due to congestion */
++};
++
++#ifdef __KERNEL__
++
++/* Standard initialization structure beginning */
++struct cryptoini {
++	int		cri_alg;	/* Algorithm to use */
++	int		cri_klen;	/* Key length, in bits */
++	int		cri_mlen;	/* Number of bytes we want from the
++					   entire hash. 0 means all. */
++	caddr_t		cri_key;	/* key to use */
++	u_int8_t	cri_iv[EALG_MAX_BLOCK_LEN];	/* IV to use */
++	struct cryptoini *cri_next;
++};
++
++/* Describe boundaries of a single crypto operation */
++struct cryptodesc {
++	int		crd_skip;	/* How many bytes to ignore from start */
++	int		crd_len;	/* How many bytes to process */
++	int		crd_inject;	/* Where to inject results, if applicable */
++	int		crd_flags;
++
++#define CRD_F_ENCRYPT		0x01	/* Set when doing encryption */
++#define CRD_F_IV_PRESENT	0x02	/* When encrypting, IV is already in
++					   place, so don't copy. */
++#define CRD_F_IV_EXPLICIT	0x04	/* IV explicitly provided */
++#define CRD_F_DSA_SHA_NEEDED	0x08	/* Compute SHA-1 of buffer for DSA */
++#define CRD_F_KEY_EXPLICIT	0x10	/* Key explicitly provided */
++#define CRD_F_COMP		0x0f    /* Set when doing compression */
++
++	struct cryptoini	CRD_INI; /* Initialization/context data */
++#define crd_iv		CRD_INI.cri_iv
++#define crd_key		CRD_INI.cri_key
++#define crd_alg		CRD_INI.cri_alg
++#define crd_klen	CRD_INI.cri_klen
++
++	struct cryptodesc *crd_next;
++};
++
++/* Structure describing complete operation */
++struct cryptop {
++	struct list_head crp_next;
++	wait_queue_head_t crp_waitq;
++
++	u_int64_t	crp_sid;	/* Session ID */
++	int		crp_ilen;	/* Input data total length */
++	int		crp_olen;	/* Result total length */
++
++	int		crp_etype;	/*
++					 * Error type (zero means no error).
++					 * All error codes except EAGAIN
++					 * indicate possible data corruption (as in,
++					 * the data have been touched). On all
++					 * errors, the crp_sid may have changed
++					 * (reset to a new one), so the caller
++					 * should always check and use the new
++					 * value on future requests.
++					 */
++	int		crp_flags;
++
++#define CRYPTO_F_SKBUF		0x0001	/* Input/output are skbuf chains */
++#define CRYPTO_F_IOV		0x0002	/* Input/output are uio */
++#define CRYPTO_F_REL		0x0004	/* Must return data in same place */
++#define CRYPTO_F_BATCH		0x0008	/* Batch op if possible */
++#define CRYPTO_F_CBIMM		0x0010	/* Do callback immediately */
++#define CRYPTO_F_DONE		0x0020	/* Operation completed */
++#define CRYPTO_F_CBIFSYNC	0x0040	/* Do CBIMM if op is synchronous */
++
++	caddr_t		crp_buf;	/* Data to be processed */
++	caddr_t		crp_opaque;	/* Opaque pointer, passed along */
++	struct cryptodesc *crp_desc;	/* Linked list of processing descriptors */
++
++	int (*crp_callback)(struct cryptop *); /* Callback function */
++};
++
++#define CRYPTO_BUF_CONTIG	0x0
++#define CRYPTO_BUF_IOV		0x1
++#define CRYPTO_BUF_SKBUF		0x2
++
++#define CRYPTO_OP_DECRYPT	0x0
++#define CRYPTO_OP_ENCRYPT	0x1
++
++/*
++ * Hints passed to process methods.
++ */
++#define CRYPTO_HINT_MORE	0x1	/* more ops coming shortly */
++
++struct cryptkop {
++	struct list_head krp_next;
++	wait_queue_head_t krp_waitq;
++
++	int		krp_flags;
++#define CRYPTO_KF_DONE		0x0001	/* Operation completed */
++#define CRYPTO_KF_CBIMM		0x0002	/* Do callback immediately */
++
++	u_int		krp_op;		/* ie. CRK_MOD_EXP or other */
++	u_int		krp_status;	/* return status */
++	u_short		krp_iparams;	/* # of input parameters */
++	u_short		krp_oparams;	/* # of output parameters */
++	u_int		krp_crid;	/* desired device, etc. */
++	u_int32_t	krp_hid;
++	struct crparam	krp_param[CRK_MAXPARAM];	/* kvm */
++	int		(*krp_callback)(struct cryptkop *);
++};
++
++#include <ocf-compat.h>
++
++/*
++ * Session ids are 64 bits.  The lower 32 bits contain a "local id" which
++ * is a driver-private session identifier.  The upper 32 bits contain a
++ * "hardware id" used by the core crypto code to identify the driver and
++ * a copy of the driver's capabilities that can be used by client code to
++ * optimize operation.
++ */
++#define CRYPTO_SESID2HID(_sid)	(((_sid) >> 32) & 0x00ffffff)
++#define CRYPTO_SESID2CAPS(_sid)	(((_sid) >> 32) & 0xff000000)
++#define CRYPTO_SESID2LID(_sid)	(((u_int32_t) (_sid)) & 0xffffffff)
++
++extern	int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard);
++extern	int crypto_freesession(u_int64_t sid);
++#define CRYPTOCAP_F_HARDWARE	CRYPTO_FLAG_HARDWARE
++#define CRYPTOCAP_F_SOFTWARE	CRYPTO_FLAG_SOFTWARE
++#define CRYPTOCAP_F_SYNC	0x04000000	/* operates synchronously */
++extern	int32_t crypto_get_driverid(device_t dev, int flags);
++extern	int crypto_find_driver(const char *);
++extern	device_t crypto_find_device_byhid(int hid);
++extern	int crypto_getcaps(int hid);
++extern	int crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
++	    u_int32_t flags);
++extern	int crypto_kregister(u_int32_t, int, u_int32_t);
++extern	int crypto_unregister(u_int32_t driverid, int alg);
++extern	int crypto_unregister_all(u_int32_t driverid);
++extern	int crypto_dispatch(struct cryptop *crp);
++extern	int crypto_kdispatch(struct cryptkop *);
++#define CRYPTO_SYMQ	0x1
++#define CRYPTO_ASYMQ	0x2
++extern	int crypto_unblock(u_int32_t, int);
++extern	void crypto_done(struct cryptop *crp);
++extern	void crypto_kdone(struct cryptkop *);
++extern	int crypto_getfeat(int *);
++
++extern	void crypto_freereq(struct cryptop *crp);
++extern	struct cryptop *crypto_getreq(int num);
++
++extern  int crypto_usercrypto;      /* userland may do crypto requests */
++extern  int crypto_userasymcrypto;  /* userland may do asym crypto reqs */
++extern  int crypto_devallowsoft;    /* only use hardware crypto */
++
++/*
++ * random number support,  crypto_unregister_all will unregister
++ */
++extern int crypto_rregister(u_int32_t driverid,
++		int (*read_random)(void *arg, u_int32_t *buf, int len), void *arg);
++extern int crypto_runregister_all(u_int32_t driverid);
++
++/*
++ * Crypto-related utility routines used mainly by drivers.
++ *
++ * XXX these don't really belong here; but for now they're
++ *     kept apart from the rest of the system.
++ */
++struct uio;
++extern	void cuio_copydata(struct uio* uio, int off, int len, caddr_t cp);
++extern	void cuio_copyback(struct uio* uio, int off, int len, caddr_t cp);
++extern	struct iovec *cuio_getptr(struct uio *uio, int loc, int *off);
++
++extern	void crypto_copyback(int flags, caddr_t buf, int off, int size,
++	    caddr_t in);
++extern	void crypto_copydata(int flags, caddr_t buf, int off, int size,
++	    caddr_t out);
++extern	int crypto_apply(int flags, caddr_t buf, int off, int len,
++	    int (*f)(void *, void *, u_int), void *arg);
++
++#endif /* __KERNEL__ */
++#endif /* _CRYPTO_CRYPTO_H_ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/cryptosoft.c linux-2.6.23.16/crypto/ocf/cryptosoft.c
+--- linux-2.6.23.16.old/crypto/ocf/cryptosoft.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/cryptosoft.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,900 @@
++/*
++ * An OCF module that uses the linux kernel cryptoapi, based on the
++ * original cryptosoft for BSD by Angelos D. Keromytis (angelos@cis.upenn.edu)
++ * but is mostly unrecognisable,
++ *
++ * Written by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2004-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this product
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ * ---------------------------------------------------------------------------
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/crypto.h>
++#include <linux/mm.h>
++#include <linux/skbuff.h>
++#include <linux/random.h>
++#include <asm/scatterlist.h>
++
++#include <cryptodev.h>
++#include <uio.h>
++
++struct {
++	softc_device_decl	sc_dev;
++} swcr_softc;
++
++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
++
++/* Software session entry */
++
++#define SW_TYPE_CIPHER		0
++#define SW_TYPE_HMAC		1
++#define SW_TYPE_AUTH2		2
++#define SW_TYPE_HASH		3
++#define SW_TYPE_COMP		4
++#define SW_TYPE_BLKCIPHER	5
++
++struct swcr_data {
++	int					sw_type;
++	int					sw_alg;
++	struct crypto_tfm	*sw_tfm;
++	union {
++		struct {
++			char *sw_key;
++			int  sw_klen;
++			int  sw_mlen;
++		} hmac;
++		void *sw_comp_buf;
++	} u;
++	struct swcr_data	*sw_next;
++};
++
++#ifndef CRYPTO_TFM_MODE_CBC
++/*
++ * As of linux-2.6.21 this is no longer defined, and presumably no longer
++ * needed to be passed into the crypto core code.
++ */
++#define	CRYPTO_TFM_MODE_CBC	0
++#define	CRYPTO_TFM_MODE_ECB	0
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++	/*
++	 * Linux 2.6.19 introduced a new Crypto API, setup macro's to convert new
++	 * API into old API.
++	 */
++
++	/* Symmetric/Block Cipher */
++	struct blkcipher_desc
++	{
++		struct crypto_tfm *tfm;
++		void *info;
++	};
++	#define ecb(X)								#X
++	#define cbc(X)								#X
++	#define crypto_has_blkcipher(X, Y, Z)		crypto_alg_available(X, 0)
++	#define crypto_blkcipher_cast(X)			X
++	#define crypto_blkcipher_tfm(X)				X
++	#define crypto_alloc_blkcipher(X, Y, Z)		crypto_alloc_tfm(X, mode)
++	#define crypto_blkcipher_ivsize(X)			crypto_tfm_alg_ivsize(X)
++	#define crypto_blkcipher_blocksize(X)		crypto_tfm_alg_blocksize(X)
++	#define crypto_blkcipher_setkey(X, Y, Z)	crypto_cipher_setkey(X, Y, Z)
++	#define crypto_blkcipher_encrypt_iv(W, X, Y, Z)	\
++				crypto_cipher_encrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
++	#define crypto_blkcipher_decrypt_iv(W, X, Y, Z)	\
++				crypto_cipher_decrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
++
++	/* Hash/HMAC/Digest */
++	struct hash_desc
++	{
++		struct crypto_tfm *tfm;
++	};
++	#define hmac(X)							#X
++	#define crypto_has_hash(X, Y, Z)		crypto_alg_available(X, 0)
++	#define crypto_hash_cast(X)				X
++	#define crypto_hash_tfm(X)				X
++	#define crypto_alloc_hash(X, Y, Z)		crypto_alloc_tfm(X, mode)
++	#define crypto_hash_digestsize(X)		crypto_tfm_alg_digestsize(X)
++	#define crypto_hash_digest(W, X, Y, Z)	\
++				crypto_digest_digest((W)->tfm, X, sg_num, Z)
++
++	/* Asymmetric Cipher */
++	#define crypto_has_cipher(X, Y, Z)		crypto_alg_available(X, 0)
++
++	/* Compression */
++	#define crypto_has_comp(X, Y, Z)		crypto_alg_available(X, 0)
++	#define crypto_comp_tfm(X)				X
++	#define crypto_comp_cast(X)				X
++	#define crypto_alloc_comp(X, Y, Z)		crypto_alloc_tfm(X, mode)
++#else
++	#define ecb(X)	"ecb(" #X ")"
++	#define cbc(X)	"cbc(" #X ")"
++	#define hmac(X)	"hmac(" #X ")"
++#endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
++
++struct crypto_details
++{
++	char *alg_name;
++	int mode;
++	int sw_type;
++};
++
++/*
++ * This needs to be kept updated with CRYPTO_xxx list (cryptodev.h).
++ * If the Algorithm is not supported, then insert a {NULL, 0, 0} entry.
++ *
++ * IMPORTANT: The index to the array IS CRYPTO_xxx.
++ */
++static struct crypto_details crypto_details[CRYPTO_ALGORITHM_MAX + 1] = {
++	{ NULL,              0,                   0 },
++	/* CRYPTO_xxx index starts at 1 */
++	{ cbc(des),          CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ cbc(des3_ede),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ cbc(blowfish),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ cbc(cast5),        CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ cbc(skipjack),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ hmac(md5),         0,                   SW_TYPE_HMAC },
++	{ hmac(sha1),        0,                   SW_TYPE_HMAC },
++	{ hmac(ripemd160),   0,                   SW_TYPE_HMAC },
++	{ "md5-kpdk??",      0,                   SW_TYPE_HASH },
++	{ "sha1-kpdk??",     0,                   SW_TYPE_HASH },
++	{ cbc(aes),          CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ ecb(arc4),         CRYPTO_TFM_MODE_ECB, SW_TYPE_BLKCIPHER },
++	{ "md5",             0,                   SW_TYPE_HASH },
++	{ "sha1",            0,                   SW_TYPE_HASH },
++	{ hmac(digest_null), 0,                   SW_TYPE_HMAC },
++	{ cbc(cipher_null),  CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ "deflate",         0,                   SW_TYPE_COMP },
++	{ hmac(sha256),      0,                   SW_TYPE_HMAC },
++	{ hmac(sha384),      0,                   SW_TYPE_HMAC },
++	{ hmac(sha512),      0,                   SW_TYPE_HMAC },
++	{ cbc(camellia),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
++	{ "sha256",          0,                   SW_TYPE_HASH },
++	{ "sha384",          0,                   SW_TYPE_HASH },
++	{ "sha512",          0,                   SW_TYPE_HASH },
++	{ "ripemd160",       0,                   SW_TYPE_HASH },
++};
++
++int32_t swcr_id = -1;
++module_param(swcr_id, int, 0444);
++MODULE_PARM_DESC(swcr_id, "Read-Only OCF ID for cryptosoft driver");
++
++int swcr_fail_if_compression_grows = 1;
++module_param(swcr_fail_if_compression_grows, int, 0644);
++MODULE_PARM_DESC(swcr_fail_if_compression_grows,
++                "Treat compression that results in more data as a failure");
++
++static struct swcr_data **swcr_sessions = NULL;
++static u_int32_t swcr_sesnum = 0;
++
++static	int swcr_process(device_t, struct cryptop *, int);
++static	int swcr_newsession(device_t, u_int32_t *, struct cryptoini *);
++static	int swcr_freesession(device_t, u_int64_t);
++
++static device_method_t swcr_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
++	DEVMETHOD(cryptodev_freesession,swcr_freesession),
++	DEVMETHOD(cryptodev_process,	swcr_process),
++};
++
++#define debug swcr_debug
++int swcr_debug = 0;
++module_param(swcr_debug, int, 0644);
++MODULE_PARM_DESC(swcr_debug, "Enable debug");
++
++/*
++ * Generate a new software session.
++ */
++static int
++swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
++{
++	struct swcr_data **swd;
++	u_int32_t i;
++	int error;
++	char *algo;
++	int mode, sw_type;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid == NULL || cri == NULL) {
++		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	if (swcr_sessions) {
++		for (i = 1; i < swcr_sesnum; i++)
++			if (swcr_sessions[i] == NULL)
++				break;
++	} else
++		i = 1;		/* NB: to silence compiler warning */
++
++	if (swcr_sessions == NULL || i == swcr_sesnum) {
++		if (swcr_sessions == NULL) {
++			i = 1; /* We leave swcr_sessions[0] empty */
++			swcr_sesnum = CRYPTO_SW_SESSIONS;
++		} else
++			swcr_sesnum *= 2;
++
++		swd = kmalloc(swcr_sesnum * sizeof(struct swcr_data *), SLAB_ATOMIC);
++		if (swd == NULL) {
++			/* Reset session number */
++			if (swcr_sesnum == CRYPTO_SW_SESSIONS)
++				swcr_sesnum = 0;
++			else
++				swcr_sesnum /= 2;
++			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++			return ENOBUFS;
++		}
++		memset(swd, 0, swcr_sesnum * sizeof(struct swcr_data *));
++
++		/* Copy existing sessions */
++		if (swcr_sessions) {
++			memcpy(swd, swcr_sessions,
++			    (swcr_sesnum / 2) * sizeof(struct swcr_data *));
++			kfree(swcr_sessions);
++		}
++
++		swcr_sessions = swd;
++	}
++
++	swd = &swcr_sessions[i];
++	*sid = i;
++
++	while (cri) {
++		*swd = (struct swcr_data *) kmalloc(sizeof(struct swcr_data),
++				SLAB_ATOMIC);
++		if (*swd == NULL) {
++			swcr_freesession(NULL, i);
++			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++			return ENOBUFS;
++		}
++		memset(*swd, 0, sizeof(struct swcr_data));
++
++		if (cri->cri_alg > CRYPTO_ALGORITHM_MAX) {
++			printk("cryptosoft: Unknown algorithm 0x%x\n", cri->cri_alg);
++			swcr_freesession(NULL, i);
++			return EINVAL;
++		}
++
++		algo = crypto_details[cri->cri_alg].alg_name;
++		if (!algo || !*algo) {
++			printk("cryptosoft: Unsupported algorithm 0x%x\n", cri->cri_alg);
++			swcr_freesession(NULL, i);
++			return EINVAL;
++		}
++
++		mode = crypto_details[cri->cri_alg].mode;
++		sw_type = crypto_details[cri->cri_alg].sw_type;
++
++		/* Algorithm specific configuration */
++		switch (cri->cri_alg) {
++		case CRYPTO_NULL_CBC:
++			cri->cri_klen = 0; /* make it work with crypto API */
++			break;
++		default:
++			break;
++		}
++
++		if (sw_type == SW_TYPE_BLKCIPHER) {
++			dprintk("%s crypto_alloc_blkcipher(%s, 0x%x)\n", __FUNCTION__,
++					algo, mode);
++
++			(*swd)->sw_tfm = crypto_blkcipher_tfm(
++								crypto_alloc_blkcipher(algo, 0,
++									CRYPTO_ALG_ASYNC));
++			if (!(*swd)->sw_tfm) {
++				dprintk("cryptosoft: crypto_alloc_blkcipher failed(%s,0x%x)\n",
++						algo,mode);
++				swcr_freesession(NULL, i);
++				return EINVAL;
++			}
++
++			if (debug) {
++				dprintk("%s key:cri->cri_klen=%d,(cri->cri_klen + 7)/8=%d",
++						__FUNCTION__,cri->cri_klen,(cri->cri_klen + 7)/8);
++				for (i = 0; i < (cri->cri_klen + 7) / 8; i++)
++				{
++					dprintk("%s0x%x", (i % 8) ? " " : "\n    ",cri->cri_key[i]);
++				}
++				dprintk("\n");
++			}
++			error = crypto_blkcipher_setkey(
++						crypto_blkcipher_cast((*swd)->sw_tfm), cri->cri_key,
++							(cri->cri_klen + 7) / 8);
++			if (error) {
++				printk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n", error,
++						(*swd)->sw_tfm->crt_flags);
++				swcr_freesession(NULL, i);
++				return error;
++			}
++		} else if (sw_type == SW_TYPE_HMAC || sw_type == SW_TYPE_HASH) {
++			dprintk("%s crypto_alloc_hash(%s, 0x%x)\n", __FUNCTION__,
++					algo, mode);
++
++			(*swd)->sw_tfm = crypto_hash_tfm(
++								crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC));
++
++			if (!(*swd)->sw_tfm) {
++				dprintk("cryptosoft: crypto_alloc_hash failed(%s,0x%x)\n",
++						algo, mode);
++				swcr_freesession(NULL, i);
++				return EINVAL;
++			}
++
++			(*swd)->u.hmac.sw_klen = (cri->cri_klen + 7) / 8;
++			(*swd)->u.hmac.sw_key = (char *)kmalloc((*swd)->u.hmac.sw_klen,
++				SLAB_ATOMIC);
++			if ((*swd)->u.hmac.sw_key == NULL) {
++				swcr_freesession(NULL, i);
++				dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++				return ENOBUFS;
++			}
++			memcpy((*swd)->u.hmac.sw_key, cri->cri_key, (*swd)->u.hmac.sw_klen);
++			if (cri->cri_mlen) {
++				(*swd)->u.hmac.sw_mlen = cri->cri_mlen;
++			} else {
++				(*swd)->u.hmac.sw_mlen =
++						crypto_hash_digestsize(
++								crypto_hash_cast((*swd)->sw_tfm));
++			}
++		} else if (sw_type == SW_TYPE_COMP) {
++			(*swd)->sw_tfm = crypto_comp_tfm(
++					crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC));
++			if (!(*swd)->sw_tfm) {
++				dprintk("cryptosoft: crypto_alloc_comp failed(%s,0x%x)\n",
++						algo, mode);
++				swcr_freesession(NULL, i);
++				return EINVAL;
++			}
++			(*swd)->u.sw_comp_buf = kmalloc(CRYPTO_MAX_DATA_LEN, SLAB_ATOMIC);
++			if ((*swd)->u.sw_comp_buf == NULL) {
++				swcr_freesession(NULL, i);
++				dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++				return ENOBUFS;
++			}
++		} else {
++			printk("cryptosoft: Unhandled sw_type %d\n", sw_type);
++			swcr_freesession(NULL, i);
++			return EINVAL;
++		}
++
++		(*swd)->sw_alg = cri->cri_alg;
++		(*swd)->sw_type = sw_type;
++
++		cri = cri->cri_next;
++		swd = &((*swd)->sw_next);
++	}
++	return 0;
++}
++
++/*
++ * Free a session.
++ */
++static int
++swcr_freesession(device_t dev, u_int64_t tid)
++{
++	struct swcr_data *swd;
++	u_int32_t sid = CRYPTO_SESID2LID(tid);
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid > swcr_sesnum || swcr_sessions == NULL ||
++			swcr_sessions[sid] == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return(EINVAL);
++	}
++
++	/* Silently accept and return */
++	if (sid == 0)
++		return(0);
++
++	while ((swd = swcr_sessions[sid]) != NULL) {
++		swcr_sessions[sid] = swd->sw_next;
++		if (swd->sw_tfm)
++			crypto_free_tfm(swd->sw_tfm);
++		if (swd->sw_type == SW_TYPE_COMP) {
++			if (swd->u.sw_comp_buf)
++				kfree(swd->u.sw_comp_buf);
++		} else {
++			if (swd->u.hmac.sw_key)
++				kfree(swd->u.hmac.sw_key);
++		}
++		kfree(swd);
++	}
++	return 0;
++}
++
++/*
++ * Process a software request.
++ */
++static int
++swcr_process(device_t dev, struct cryptop *crp, int hint)
++{
++	struct cryptodesc *crd;
++	struct swcr_data *sw;
++	u_int32_t lid;
++#define SCATTERLIST_MAX 16
++	struct scatterlist sg[SCATTERLIST_MAX];
++	int sg_num, sg_len, skip;
++	struct sk_buff *skb = NULL;
++	struct uio *uiop = NULL;
++
++	dprintk("%s()\n", __FUNCTION__);
++	/* Sanity check */
++	if (crp == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	crp->crp_etype = 0;
++
++	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		crp->crp_etype = EINVAL;
++		goto done;
++	}
++
++	lid = crp->crp_sid & 0xffffffff;
++	if (lid >= swcr_sesnum || lid == 0 || swcr_sessions == NULL ||
++			swcr_sessions[lid] == NULL) {
++		crp->crp_etype = ENOENT;
++		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
++		goto done;
++	}
++
++	/*
++	 * do some error checking outside of the loop for SKB and IOV processing
++	 * this leaves us with valid skb or uiop pointers for later
++	 */
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		skb = (struct sk_buff *) crp->crp_buf;
++		if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) {
++			printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__, __LINE__,
++					skb_shinfo(skb)->nr_frags);
++			goto done;
++		}
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		uiop = (struct uio *) crp->crp_buf;
++		if (uiop->uio_iovcnt > SCATTERLIST_MAX) {
++			printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__, __LINE__,
++					uiop->uio_iovcnt);
++			goto done;
++		}
++	}
++
++	/* Go through crypto descriptors, processing as we go */
++	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
++		/*
++		 * Find the crypto context.
++		 *
++		 * XXX Note that the logic here prevents us from having
++		 * XXX the same algorithm multiple times in a session
++		 * XXX (or rather, we can but it won't give us the right
++		 * XXX results). To do that, we'd need some way of differentiating
++		 * XXX between the various instances of an algorithm (so we can
++		 * XXX locate the correct crypto context).
++		 */
++		for (sw = swcr_sessions[lid]; sw && sw->sw_alg != crd->crd_alg;
++				sw = sw->sw_next)
++			;
++
++		/* No such context ? */
++		if (sw == NULL) {
++			crp->crp_etype = EINVAL;
++			dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++			goto done;
++		}
++
++		skip = crd->crd_skip;
++
++		/*
++		 * setup the SG list skip from the start of the buffer
++		 */
++		memset(sg, 0, sizeof(sg));
++		if (crp->crp_flags & CRYPTO_F_SKBUF) {
++			int i, len;
++
++			sg_num = 0;
++			sg_len = 0;
++
++			if (skip < skb_headlen(skb)) {
++				sg[sg_num].page   = virt_to_page(skb->data + skip);
++				sg[sg_num].offset = offset_in_page(skb->data + skip);
++				len = skb_headlen(skb) - skip;
++				if (len + sg_len > crd->crd_len)
++					len = crd->crd_len - sg_len;
++				sg[sg_num].length = len;
++				sg_len += sg[sg_num].length;
++				sg_num++;
++				skip = 0;
++			} else
++				skip -= skb_headlen(skb);
++
++			for (i = 0; sg_len < crd->crd_len &&
++						i < skb_shinfo(skb)->nr_frags &&
++						sg_num < SCATTERLIST_MAX; i++) {
++				if (skip < skb_shinfo(skb)->frags[i].size) {
++					sg[sg_num].page   = skb_shinfo(skb)->frags[i].page;
++					sg[sg_num].offset = skb_shinfo(skb)->frags[i].page_offset +
++							skip;
++					len = skb_shinfo(skb)->frags[i].size - skip;
++					if (len + sg_len > crd->crd_len)
++						len = crd->crd_len - sg_len;
++					sg[sg_num].length = len;
++					sg_len += sg[sg_num].length;
++					sg_num++;
++					skip = 0;
++				} else
++					skip -= skb_shinfo(skb)->frags[i].size;
++			}
++		} else if (crp->crp_flags & CRYPTO_F_IOV) {
++			int len;
++
++			sg_len = 0;
++			for (sg_num = 0; sg_len <= crd->crd_len &&
++					sg_num < uiop->uio_iovcnt &&
++					sg_num < SCATTERLIST_MAX; sg_num++) {
++				if (skip <= uiop->uio_iov[sg_num].iov_len) {
++					sg[sg_num].page   =
++							virt_to_page(uiop->uio_iov[sg_num].iov_base+skip);
++					sg[sg_num].offset =
++							offset_in_page(uiop->uio_iov[sg_num].iov_base+skip);
++					len = uiop->uio_iov[sg_num].iov_len - skip;
++					if (len + sg_len > crd->crd_len)
++						len = crd->crd_len - sg_len;
++					sg[sg_num].length = len;
++					sg_len += sg[sg_num].length;
++					skip = 0;
++				} else 
++					skip -= uiop->uio_iov[sg_num].iov_len;
++			}
++		} else {
++			sg[0].page   = virt_to_page(crp->crp_buf + skip);
++			sg[0].offset = offset_in_page(crp->crp_buf + skip);
++			sg_len = (crp->crp_ilen - skip);
++			if (sg_len > crd->crd_len)
++				sg_len = crd->crd_len;
++			sg[0].length = sg_len;
++			sg_num = 1;
++		}
++
++
++		switch (sw->sw_type) {
++		case SW_TYPE_BLKCIPHER: {
++			unsigned char iv[EALG_MAX_BLOCK_LEN];
++			unsigned char *ivp = iv;
++			int ivsize = 
++				crypto_blkcipher_ivsize(crypto_blkcipher_cast(sw->sw_tfm));
++			struct blkcipher_desc desc;
++
++			if (sg_len < crypto_blkcipher_blocksize(
++					crypto_blkcipher_cast(sw->sw_tfm))) {
++				crp->crp_etype = EINVAL;
++				dprintk("%s,%d: EINVAL len %d < %d\n", __FILE__, __LINE__,
++						sg_len, crypto_blkcipher_blocksize(
++							crypto_blkcipher_cast(sw->sw_tfm)));
++				goto done;
++			}
++
++			if (ivsize > sizeof(iv)) {
++				crp->crp_etype = EINVAL;
++				dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++				goto done;
++			}
++
++			if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
++				int i, error;
++
++				if (debug) {
++					dprintk("%s key:", __FUNCTION__);
++					for (i = 0; i < (crd->crd_klen + 7) / 8; i++)
++						dprintk("%s0x%x", (i % 8) ? " " : "\n    ",
++								crd->crd_key[i]);
++					dprintk("\n");
++				}
++				error = crypto_blkcipher_setkey(
++							crypto_blkcipher_cast(sw->sw_tfm), crd->crd_key,
++							(crd->crd_klen + 7) / 8);
++				if (error) {
++					dprintk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n",
++							error, sw->sw_tfm->crt_flags);
++					crp->crp_etype = -error;
++				}
++			}
++
++			memset(&desc, 0, sizeof(desc));
++			desc.tfm = crypto_blkcipher_cast(sw->sw_tfm);
++
++			if (crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
++
++				if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
++					ivp = crd->crd_iv;
++				} else {
++					get_random_bytes(ivp, ivsize);
++				}
++				/*
++				 * do we have to copy the IV back to the buffer ?
++				 */
++				if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
++					crypto_copyback(crp->crp_flags, crp->crp_buf,
++							crd->crd_inject, ivsize, (caddr_t)ivp);
++				}
++				desc.info = ivp;
++				crypto_blkcipher_encrypt_iv(&desc, sg, sg, sg_len);
++
++			} else { /*decrypt */
++
++				if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
++					ivp = crd->crd_iv;
++				} else {
++					crypto_copydata(crp->crp_flags, crp->crp_buf,
++							crd->crd_inject, ivsize, (caddr_t)ivp);
++				}
++				desc.info = ivp;
++				crypto_blkcipher_decrypt_iv(&desc, sg, sg, sg_len);
++			}
++			} break;
++		case SW_TYPE_HMAC:
++		case SW_TYPE_HASH:
++			{
++			char result[HASH_MAX_LEN];
++			struct hash_desc desc;
++
++			/* check we have room for the result */
++			if (crp->crp_ilen - crd->crd_inject < sw->u.hmac.sw_mlen) {
++				dprintk(
++			"cryptosoft: EINVAL crp_ilen=%d, len=%d, inject=%d digestsize=%d\n",
++						crp->crp_ilen, crd->crd_skip + sg_len, crd->crd_inject,
++						sw->u.hmac.sw_mlen);
++				crp->crp_etype = EINVAL;
++				goto done;
++			}
++
++			memset(&desc, 0, sizeof(desc));
++			desc.tfm = crypto_hash_cast(sw->sw_tfm);
++
++			memset(result, 0, sizeof(result));
++
++			if (sw->sw_type == SW_TYPE_HMAC) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++				crypto_hmac(sw->sw_tfm, sw->u.hmac.sw_key, &sw->u.hmac.sw_klen,
++						sg, sg_num, result);
++#else
++				crypto_hash_setkey(desc.tfm, sw->u.hmac.sw_key,
++						sw->u.hmac.sw_klen);
++				crypto_hash_digest(&desc, sg, sg_len, result);
++#endif /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
++				
++			} else { /* SW_TYPE_HASH */
++				crypto_hash_digest(&desc, sg, sg_len, result);
++			}
++
++			crypto_copyback(crp->crp_flags, crp->crp_buf,
++					crd->crd_inject, sw->u.hmac.sw_mlen, result);
++			}
++			break;
++
++		case SW_TYPE_COMP: {
++			void *ibuf = NULL;
++			void *obuf = sw->u.sw_comp_buf;
++			int ilen = sg_len, olen = CRYPTO_MAX_DATA_LEN;
++			int ret = 0;
++
++			/*
++			 * we need to use an additional copy if there is more than one
++			 * input chunk since the kernel comp routines do not handle
++			 * SG yet.  Otherwise we just use the input buffer as is.
++			 * Rather than allocate another buffer we just split the tmp
++			 * buffer we already have.
++			 * Perhaps we should just use zlib directly ?
++			 */
++			if (sg_num > 1) {
++				int blk;
++
++				ibuf = obuf;
++				for (blk = 0; blk < sg_num; blk++) {
++					memcpy(obuf, page_address(sg[blk].page) + sg[blk].offset,
++							sg[blk].length);
++					obuf += sg[blk].length;
++				}
++				olen -= sg_len;
++			} else
++				ibuf = page_address(sg[0].page) + sg[0].offset;
++
++			if (crd->crd_flags & CRD_F_ENCRYPT) { /* compress */
++				ret = crypto_comp_compress(crypto_comp_cast(sw->sw_tfm),
++						ibuf, ilen, obuf, &olen);
++				if (!ret && olen > crd->crd_len) {
++					dprintk("cryptosoft: ERANGE compress %d into %d\n",
++							crd->crd_len, olen);
++					if (swcr_fail_if_compression_grows)
++						ret = ERANGE;
++				}
++			} else { /* decompress */
++				ret = crypto_comp_decompress(crypto_comp_cast(sw->sw_tfm),
++						ibuf, ilen, obuf, &olen);
++				if (!ret && (olen + crd->crd_inject) > crp->crp_olen) {
++					dprintk("cryptosoft: ETOOSMALL decompress %d into %d, "
++							"space for %d,at offset %d\n",
++							crd->crd_len, olen, crp->crp_olen, crd->crd_inject);
++					ret = ETOOSMALL;
++				}
++			}
++			if (ret)
++				dprintk("%s,%d: ret = %d\n", __FILE__, __LINE__, ret);
++
++			/*
++			 * on success copy result back,
++			 * linux crpyto API returns -errno,  we need to fix that
++			 */
++			crp->crp_etype = ret < 0 ? -ret : ret;
++			if (ret == 0) {
++				/* copy back the result and return it's size */
++				crypto_copyback(crp->crp_flags, crp->crp_buf,
++						crd->crd_inject, olen, obuf);
++				crp->crp_olen = olen;
++			}
++
++
++			} break;
++
++		default:
++			/* Unknown/unsupported algorithm */
++			dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++			crp->crp_etype = EINVAL;
++			goto done;
++		}
++	}
++
++done:
++	crypto_done(crp);
++	return 0;
++}
++
++static int
++cryptosoft_init(void)
++{
++	int i, sw_type, mode;
++	char *algo;
++
++	dprintk("%s(%p)\n", __FUNCTION__, cryptosoft_init);
++
++	softc_device_init(&swcr_softc, "cryptosoft", 0, swcr_methods);
++
++	swcr_id = crypto_get_driverid(softc_get_device(&swcr_softc),
++			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
++	if (swcr_id < 0) {
++		printk("Software crypto device cannot initialize!");
++		return -ENODEV;
++	}
++
++#define	REGISTER(alg) \
++		crypto_register(swcr_id, alg, 0,0);
++
++	for (i = CRYPTO_ALGORITHM_MIN; i <= CRYPTO_ALGORITHM_MAX; ++i)
++	{
++		
++		algo = crypto_details[i].alg_name;
++		if (!algo || !*algo)
++		{
++			dprintk("%s:Algorithm %d not supported\n", __FUNCTION__, i);
++			continue;
++		}
++
++		mode = crypto_details[i].mode;
++		sw_type = crypto_details[i].sw_type;
++
++		switch (sw_type)
++		{
++			case SW_TYPE_CIPHER:
++				if (crypto_has_cipher(algo, 0, CRYPTO_ALG_ASYNC))
++				{
++					REGISTER(i);
++				}
++				else
++				{
++					dprintk("%s:CIPHER algorithm %d:'%s' not supported\n",
++								__FUNCTION__, i, algo);
++				}
++				break;
++			case SW_TYPE_HMAC:
++				if (crypto_has_hash(algo, 0, CRYPTO_ALG_ASYNC))
++				{
++					REGISTER(i);
++				}
++				else
++				{
++					dprintk("%s:HMAC algorithm %d:'%s' not supported\n",
++								__FUNCTION__, i, algo);
++				}
++				break;
++			case SW_TYPE_HASH:
++				if (crypto_has_hash(algo, 0, CRYPTO_ALG_ASYNC))
++				{
++					REGISTER(i);
++				}
++				else
++				{
++					dprintk("%s:HASH algorithm %d:'%s' not supported\n",
++								__FUNCTION__, i, algo);
++				}
++				break;
++			case SW_TYPE_COMP:
++				if (crypto_has_comp(algo, 0, CRYPTO_ALG_ASYNC))
++				{
++					REGISTER(i);
++				}
++				else
++				{
++					dprintk("%s:COMP algorithm %d:'%s' not supported\n",
++								__FUNCTION__, i, algo);
++				}
++				break;
++			case SW_TYPE_BLKCIPHER:
++				if (crypto_has_blkcipher(algo, 0, CRYPTO_ALG_ASYNC))
++				{
++					REGISTER(i);
++				}
++				else
++				{
++					dprintk("%s:BLKCIPHER algorithm %d:'%s' not supported\n",
++								__FUNCTION__, i, algo);
++				}
++				break;
++			default:
++				dprintk(
++				"%s:Algorithm Type %d not supported (algorithm %d:'%s')\n",
++					__FUNCTION__, sw_type, i, algo);
++				break;
++		}
++	}
++
++	return(0);
++}
++
++static void
++cryptosoft_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	crypto_unregister_all(swcr_id);
++	swcr_id = -1;
++}
++
++module_init(cryptosoft_init);
++module_exit(cryptosoft_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("Cryptosoft (OCF module for kernel crypto)");
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/hifn7751.c linux-2.6.23.16/crypto/ocf/hifn/hifn7751.c
+--- linux-2.6.23.16.old/crypto/ocf/hifn/hifn7751.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/hifn7751.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,2969 @@
++/*	$OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $	*/
++
++/*-
++ * Invertex AEON / Hifn 7751 driver
++ * Copyright (c) 1999 Invertex Inc. All rights reserved.
++ * Copyright (c) 1999 Theo de Raadt
++ * Copyright (c) 2000-2001 Network Security Technologies, Inc.
++ *			http://www.netsec.net
++ * Copyright (c) 2003 Hifn Inc.
++ *
++ * This driver is based on a previous driver by Invertex, for which they
++ * requested:  Please send any comments, feedback, bug-fixes, or feature
++ * requests to software@invertex.com.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *   derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
++ *
++ *
++__FBSDID("$FreeBSD: src/sys/dev/hifn/hifn7751.c,v 1.40 2007/03/21 03:42:49 sam Exp $");
++ */
++
++/*
++ * Driver for various Hifn encryption processors.
++ */
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/random.h>
++#include <linux/version.h>
++#include <linux/skbuff.h>
++#include <asm/io.h>
++
++#include <cryptodev.h>
++#include <uio.h>
++#include <hifn/hifn7751reg.h>
++#include <hifn/hifn7751var.h>
++
++#if 1
++#define	DPRINTF(a...)	if (hifn_debug) { \
++							printk("%s: ", sc ? \
++								device_get_nameunit(sc->sc_dev) : "hifn"); \
++							printk(a); \
++						} else
++#else
++#define	DPRINTF(a...)
++#endif
++
++static inline int
++pci_get_revid(struct pci_dev *dev)
++{
++	u8 rid = 0;
++	pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
++	return rid;
++}
++
++static	struct hifn_stats hifnstats;
++
++#define	debug hifn_debug
++int hifn_debug = 0;
++module_param(hifn_debug, int, 0644);
++MODULE_PARM_DESC(hifn_debug, "Enable debug");
++
++int hifn_maxbatch = 1;
++module_param(hifn_maxbatch, int, 0644);
++MODULE_PARM_DESC(hifn_maxbatch, "max ops to batch w/o interrupt");
++
++#ifdef MODULE_PARM
++char *hifn_pllconfig = NULL;
++MODULE_PARM(hifn_pllconfig, "s");
++#else
++char hifn_pllconfig[32]; /* This setting is RO after loading */
++module_param_string(hifn_pllconfig, hifn_pllconfig, 32, 0444);
++#endif
++MODULE_PARM_DESC(hifn_pllconfig, "PLL config, ie., pci66, ext33, ...");
++
++#ifdef HIFN_VULCANDEV
++#include <sys/conf.h>
++#include <sys/uio.h>
++
++static struct cdevsw vulcanpk_cdevsw; /* forward declaration */
++#endif
++
++/*
++ * Prototypes and count for the pci_device structure
++ */
++static	int  hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent);
++static	void hifn_remove(struct pci_dev *dev);
++
++static	int hifn_newsession(device_t, u_int32_t *, struct cryptoini *);
++static	int hifn_freesession(device_t, u_int64_t);
++static	int hifn_process(device_t, struct cryptop *, int);
++
++static device_method_t hifn_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	hifn_newsession),
++	DEVMETHOD(cryptodev_freesession,hifn_freesession),
++	DEVMETHOD(cryptodev_process,	hifn_process),
++};
++
++static	void hifn_reset_board(struct hifn_softc *, int);
++static	void hifn_reset_puc(struct hifn_softc *);
++static	void hifn_puc_wait(struct hifn_softc *);
++static	int hifn_enable_crypto(struct hifn_softc *);
++static	void hifn_set_retry(struct hifn_softc *sc);
++static	void hifn_init_dma(struct hifn_softc *);
++static	void hifn_init_pci_registers(struct hifn_softc *);
++static	int hifn_sramsize(struct hifn_softc *);
++static	int hifn_dramsize(struct hifn_softc *);
++static	int hifn_ramtype(struct hifn_softc *);
++static	void hifn_sessions(struct hifn_softc *);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++static irqreturn_t hifn_intr(int irq, void *arg);
++#else
++static irqreturn_t hifn_intr(int irq, void *arg, struct pt_regs *regs);
++#endif
++static	u_int hifn_write_command(struct hifn_command *, u_int8_t *);
++static	u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);
++static	void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);
++static	int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);
++static	int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);
++static	int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *);
++static	int hifn_dmamap_load_src(struct hifn_softc *, struct hifn_command *);
++static	int hifn_dmamap_load_dst(struct hifn_softc *, struct hifn_command *);
++static	int hifn_init_pubrng(struct hifn_softc *);
++static	void hifn_tick(unsigned long arg);
++static	void hifn_abort(struct hifn_softc *);
++static	void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, int *);
++
++static	void hifn_write_reg_0(struct hifn_softc *, bus_size_t, u_int32_t);
++static	void hifn_write_reg_1(struct hifn_softc *, bus_size_t, u_int32_t);
++
++#ifdef CONFIG_OCF_RANDOMHARVEST
++static	int hifn_read_random(void *arg, u_int32_t *buf, int len);
++#endif
++
++#define HIFN_MAX_CHIPS	8
++static struct hifn_softc *hifn_chip_idx[HIFN_MAX_CHIPS];
++
++static __inline u_int32_t
++READ_REG_0(struct hifn_softc *sc, bus_size_t reg)
++{
++	u_int32_t v = readl(sc->sc_bar0 + reg);
++	sc->sc_bar0_lastreg = (bus_size_t) -1;
++	return (v);
++}
++#define	WRITE_REG_0(sc, reg, val)	hifn_write_reg_0(sc, reg, val)
++
++static __inline u_int32_t
++READ_REG_1(struct hifn_softc *sc, bus_size_t reg)
++{
++	u_int32_t v = readl(sc->sc_bar1 + reg);
++	sc->sc_bar1_lastreg = (bus_size_t) -1;
++	return (v);
++}
++#define	WRITE_REG_1(sc, reg, val)	hifn_write_reg_1(sc, reg, val)
++
++/*
++ * map in a given buffer (great on some arches :-)
++ */
++
++static int
++pci_map_uio(struct hifn_softc *sc, struct hifn_operand *buf, struct uio *uio)
++{
++	struct iovec *iov = uio->uio_iov;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	buf->mapsize = 0;
++	for (buf->nsegs = 0; buf->nsegs < uio->uio_iovcnt; ) {
++		buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_pcidev,
++				iov->iov_base, iov->iov_len,
++				PCI_DMA_BIDIRECTIONAL);
++		buf->segs[buf->nsegs].ds_len = iov->iov_len;
++		buf->mapsize += iov->iov_len;
++		iov++;
++		buf->nsegs++;
++	}
++	/* identify this buffer by the first segment */
++	buf->map = (void *) buf->segs[0].ds_addr;
++	return(0);
++}
++
++/*
++ * map in a given sk_buff
++ */
++
++static int
++pci_map_skb(struct hifn_softc *sc,struct hifn_operand *buf,struct sk_buff *skb)
++{
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	buf->mapsize = 0;
++
++	buf->segs[0].ds_addr = pci_map_single(sc->sc_pcidev,
++			skb->data, skb_headlen(skb), PCI_DMA_BIDIRECTIONAL);
++	buf->segs[0].ds_len = skb_headlen(skb);
++	buf->mapsize += buf->segs[0].ds_len;
++
++	buf->nsegs = 1;
++
++	for (i = 0; i < skb_shinfo(skb)->nr_frags; ) {
++		buf->segs[buf->nsegs].ds_len = skb_shinfo(skb)->frags[i].size;
++		buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_pcidev,
++				page_address(skb_shinfo(skb)->frags[i].page) +
++					skb_shinfo(skb)->frags[i].page_offset,
++				buf->segs[buf->nsegs].ds_len, PCI_DMA_BIDIRECTIONAL);
++		buf->mapsize += buf->segs[buf->nsegs].ds_len;
++		buf->nsegs++;
++	}
++
++	/* identify this buffer by the first segment */
++	buf->map = (void *) buf->segs[0].ds_addr;
++	return(0);
++}
++
++/*
++ * map in a given contiguous buffer
++ */
++
++static int
++pci_map_buf(struct hifn_softc *sc,struct hifn_operand *buf, void *b, int len)
++{
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	buf->mapsize = 0;
++	buf->segs[0].ds_addr = pci_map_single(sc->sc_pcidev,
++			b, len, PCI_DMA_BIDIRECTIONAL);
++	buf->segs[0].ds_len = len;
++	buf->mapsize += buf->segs[0].ds_len;
++	buf->nsegs = 1;
++
++	/* identify this buffer by the first segment */
++	buf->map = (void *) buf->segs[0].ds_addr;
++	return(0);
++}
++
++#if 0 /* not needed at this time */
++static void
++pci_sync_iov(struct hifn_softc *sc, struct hifn_operand *buf)
++{
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++	for (i = 0; i < buf->nsegs; i++)
++		pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
++				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
++}
++#endif
++
++static void
++pci_unmap_buf(struct hifn_softc *sc, struct hifn_operand *buf)
++{
++	int i;
++	DPRINTF("%s()\n", __FUNCTION__);
++	for (i = 0; i < buf->nsegs; i++) {
++		pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
++				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
++		buf->segs[i].ds_addr = 0;
++		buf->segs[i].ds_len = 0;
++	}
++	buf->nsegs = 0;
++	buf->mapsize = 0;
++	buf->map = 0;
++}
++
++static const char*
++hifn_partname(struct hifn_softc *sc)
++{
++	/* XXX sprintf numbers when not decoded */
++	switch (pci_get_vendor(sc->sc_pcidev)) {
++	case PCI_VENDOR_HIFN:
++		switch (pci_get_device(sc->sc_pcidev)) {
++		case PCI_PRODUCT_HIFN_6500:	return "Hifn 6500";
++		case PCI_PRODUCT_HIFN_7751:	return "Hifn 7751";
++		case PCI_PRODUCT_HIFN_7811:	return "Hifn 7811";
++		case PCI_PRODUCT_HIFN_7951:	return "Hifn 7951";
++		case PCI_PRODUCT_HIFN_7955:	return "Hifn 7955";
++		case PCI_PRODUCT_HIFN_7956:	return "Hifn 7956";
++		}
++		return "Hifn unknown-part";
++	case PCI_VENDOR_INVERTEX:
++		switch (pci_get_device(sc->sc_pcidev)) {
++		case PCI_PRODUCT_INVERTEX_AEON:	return "Invertex AEON";
++		}
++		return "Invertex unknown-part";
++	case PCI_VENDOR_NETSEC:
++		switch (pci_get_device(sc->sc_pcidev)) {
++		case PCI_PRODUCT_NETSEC_7751:	return "NetSec 7751";
++		}
++		return "NetSec unknown-part";
++	}
++	return "Unknown-vendor unknown-part";
++}
++
++static u_int
++checkmaxmin(struct pci_dev *dev, const char *what, u_int v, u_int min, u_int max)
++{
++	struct hifn_softc *sc = pci_get_drvdata(dev);
++	if (v > max) {
++		device_printf(sc->sc_dev, "Warning, %s %u out of range, "
++			"using max %u\n", what, v, max);
++		v = max;
++	} else if (v < min) {
++		device_printf(sc->sc_dev, "Warning, %s %u out of range, "
++			"using min %u\n", what, v, min);
++		v = min;
++	}
++	return v;
++}
++
++/*
++ * Select PLL configuration for 795x parts.  This is complicated in
++ * that we cannot determine the optimal parameters without user input.
++ * The reference clock is derived from an external clock through a
++ * multiplier.  The external clock is either the host bus (i.e. PCI)
++ * or an external clock generator.  When using the PCI bus we assume
++ * the clock is either 33 or 66 MHz; for an external source we cannot
++ * tell the speed.
++ *
++ * PLL configuration is done with a string: "pci" for PCI bus, or "ext"
++ * for an external source, followed by the frequency.  We calculate
++ * the appropriate multiplier and PLL register contents accordingly.
++ * When no configuration is given we default to "pci66" since that
++ * always will allow the card to work.  If a card is using the PCI
++ * bus clock and in a 33MHz slot then it will be operating at half
++ * speed until the correct information is provided.
++ *
++ * We use a default setting of "ext66" because according to Mike Ham
++ * of HiFn, almost every board in existence has an external crystal
++ * populated at 66Mhz. Using PCI can be a problem on modern motherboards,
++ * because PCI33 can have clocks from 0 to 33Mhz, and some have
++ * non-PCI-compliant spread-spectrum clocks, which can confuse the pll.
++ */
++static void
++hifn_getpllconfig(struct pci_dev *dev, u_int *pll)
++{
++	const char *pllspec = hifn_pllconfig;
++	u_int freq, mul, fl, fh;
++	u_int32_t pllconfig;
++	char *nxt;
++
++	if (pllspec == NULL)
++		pllspec = "ext66";
++	fl = 33, fh = 66;
++	pllconfig = 0;
++	if (strncmp(pllspec, "ext", 3) == 0) {
++		pllspec += 3;
++		pllconfig |= HIFN_PLL_REF_SEL;
++		switch (pci_get_device(dev)) {
++		case PCI_PRODUCT_HIFN_7955:
++		case PCI_PRODUCT_HIFN_7956:
++			fl = 20, fh = 100;
++			break;
++#ifdef notyet
++		case PCI_PRODUCT_HIFN_7954:
++			fl = 20, fh = 66;
++			break;
++#endif
++		}
++	} else if (strncmp(pllspec, "pci", 3) == 0)
++		pllspec += 3;
++	freq = strtoul(pllspec, &nxt, 10);
++	if (nxt == pllspec)
++		freq = 66;
++	else
++		freq = checkmaxmin(dev, "frequency", freq, fl, fh);
++	/*
++	 * Calculate multiplier.  We target a Fck of 266 MHz,
++	 * allowing only even values, possibly rounded down.
++	 * Multipliers > 8 must set the charge pump current.
++	 */
++	mul = checkmaxmin(dev, "PLL divisor", (266 / freq) &~ 1, 2, 12);
++	pllconfig |= (mul / 2 - 1) << HIFN_PLL_ND_SHIFT;
++	if (mul > 8)
++		pllconfig |= HIFN_PLL_IS;
++	*pll = pllconfig;
++}
++
++/*
++ * Attach an interface that successfully probed.
++ */
++static int
++hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++{
++	struct hifn_softc *sc = NULL;
++	char rbase;
++	u_int16_t ena, rev;
++	int rseg, rc;
++	unsigned long mem_start, mem_len;
++	static int num_chips = 0;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (pci_enable_device(dev) < 0)
++		return(-ENODEV);
++
++	if (pci_set_mwi(dev))
++		return(-ENODEV);
++
++	if (!dev->irq) {
++		printk("hifn: found device with no IRQ assigned. check BIOS settings!");
++		pci_disable_device(dev);
++		return(-ENODEV);
++	}
++
++	sc = (struct hifn_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
++	if (!sc)
++		return(-ENOMEM);
++	memset(sc, 0, sizeof(*sc));
++
++	softc_device_init(sc, "hifn", num_chips, hifn_methods);
++
++	sc->sc_pcidev = dev;
++	sc->sc_irq = -1;
++	sc->sc_cid = -1;
++	sc->sc_num = num_chips++;
++	if (sc->sc_num < HIFN_MAX_CHIPS)
++		hifn_chip_idx[sc->sc_num] = sc;
++
++	pci_set_drvdata(sc->sc_pcidev, sc);
++
++	spin_lock_init(&sc->sc_mtx);
++
++	/* XXX handle power management */
++
++	/*
++	 * The 7951 and 795x have a random number generator and
++	 * public key support; note this.
++	 */
++	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
++	    (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
++	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
++	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
++		sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;
++	/*
++	 * The 7811 has a random number generator and
++	 * we also note it's identity 'cuz of some quirks.
++	 */
++	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
++	    pci_get_device(dev) == PCI_PRODUCT_HIFN_7811)
++		sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;
++
++	/*
++	 * The 795x parts support AES.
++	 */
++	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
++	    (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
++	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7956)) {
++		sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
++		/*
++		 * Select PLL configuration.  This depends on the
++		 * bus and board design and must be manually configured
++		 * if the default setting is unacceptable.
++		 */
++		hifn_getpllconfig(dev, &sc->sc_pllconfig);
++	}
++
++	/*
++	 * Setup PCI resources. Note that we record the bus
++	 * tag and handle for each register mapping, this is
++	 * used by the READ_REG_0, WRITE_REG_0, READ_REG_1,
++	 * and WRITE_REG_1 macros throughout the driver.
++	 */
++	mem_start = pci_resource_start(sc->sc_pcidev, 0);
++	mem_len   = pci_resource_len(sc->sc_pcidev, 0);
++	sc->sc_bar0 = (ocf_iomem_t) ioremap(mem_start, mem_len);
++	if (!sc->sc_bar0) {
++		device_printf(sc->sc_dev, "cannot map bar%d register space\n", 0);
++		goto fail;
++	}
++	sc->sc_bar0_lastreg = (bus_size_t) -1;
++
++	mem_start = pci_resource_start(sc->sc_pcidev, 1);
++	mem_len   = pci_resource_len(sc->sc_pcidev, 1);
++	sc->sc_bar1 = (ocf_iomem_t) ioremap(mem_start, mem_len);
++	if (!sc->sc_bar1) {
++		device_printf(sc->sc_dev, "cannot map bar%d register space\n", 1);
++		goto fail;
++	}
++	sc->sc_bar1_lastreg = (bus_size_t) -1;
++
++	/* fix up the bus size */
++	if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
++		device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
++		goto fail;
++	}
++	if (pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK)) {
++		device_printf(sc->sc_dev,
++				"No usable consistent DMA configuration, aborting.\n");
++		goto fail;
++	}
++
++	hifn_set_retry(sc);
++
++	/*
++	 * Setup the area where the Hifn DMA's descriptors
++	 * and associated data structures.
++	 */
++	sc->sc_dma = (struct hifn_dma *) pci_alloc_consistent(dev,
++			sizeof(*sc->sc_dma),
++			&sc->sc_dma_physaddr);
++	if (!sc->sc_dma) {
++		device_printf(sc->sc_dev, "cannot alloc sc_dma\n");
++		goto fail;
++	}
++	bzero(sc->sc_dma, sizeof(*sc->sc_dma));
++
++	/*
++	 * Reset the board and do the ``secret handshake''
++	 * to enable the crypto support.  Then complete the
++	 * initialization procedure by setting up the interrupt
++	 * and hooking in to the system crypto support so we'll
++	 * get used for system services like the crypto device,
++	 * IPsec, RNG device, etc.
++	 */
++	hifn_reset_board(sc, 0);
++
++	if (hifn_enable_crypto(sc) != 0) {
++		device_printf(sc->sc_dev, "crypto enabling failed\n");
++		goto fail;
++	}
++	hifn_reset_puc(sc);
++
++	hifn_init_dma(sc);
++	hifn_init_pci_registers(sc);
++
++	pci_set_master(sc->sc_pcidev);
++
++	/* XXX can't dynamically determine ram type for 795x; force dram */
++	if (sc->sc_flags & HIFN_IS_7956)
++		sc->sc_drammodel = 1;
++	else if (hifn_ramtype(sc))
++		goto fail;
++
++	if (sc->sc_drammodel == 0)
++		hifn_sramsize(sc);
++	else
++		hifn_dramsize(sc);
++
++	/*
++	 * Workaround for NetSec 7751 rev A: half ram size because two
++	 * of the address lines were left floating
++	 */
++	if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
++	    pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751 &&
++	    pci_get_revid(dev) == 0x61)	/*XXX???*/
++		sc->sc_ramsize >>= 1;
++
++	/*
++	 * Arrange the interrupt line.
++	 */
++	rc = request_irq(dev->irq, hifn_intr, IRQF_SHARED, "hifn", sc);
++	if (rc) {
++		device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
++		goto fail;
++	}
++	sc->sc_irq = dev->irq;
++
++	hifn_sessions(sc);
++
++	/*
++	 * NB: Keep only the low 16 bits; this masks the chip id
++	 *     from the 7951.
++	 */
++	rev = READ_REG_1(sc, HIFN_1_REVID) & 0xffff;
++
++	rseg = sc->sc_ramsize / 1024;
++	rbase = 'K';
++	if (sc->sc_ramsize >= (1024 * 1024)) {
++		rbase = 'M';
++		rseg /= 1024;
++	}
++	device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram",
++		hifn_partname(sc), rev,
++		rseg, rbase, sc->sc_drammodel ? 'd' : 's');
++	if (sc->sc_flags & HIFN_IS_7956)
++		printf(", pll=0x%x<%s clk, %ux mult>",
++			sc->sc_pllconfig,
++			sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
++			2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
++	printf("\n");
++
++	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
++	if (sc->sc_cid < 0) {
++		device_printf(sc->sc_dev, "could not get crypto driver id\n");
++		goto fail;
++	}
++
++	WRITE_REG_0(sc, HIFN_0_PUCNFG,
++	    READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);
++	ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
++
++	switch (ena) {
++	case HIFN_PUSTAT_ENA_2:
++		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
++		if (sc->sc_flags & HIFN_HAS_AES)
++			crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
++		/*FALLTHROUGH*/
++	case HIFN_PUSTAT_ENA_1:
++		crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
++		break;
++	}
++
++	if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG))
++		hifn_init_pubrng(sc);
++
++	init_timer(&sc->sc_tickto);
++	sc->sc_tickto.function = hifn_tick;
++	sc->sc_tickto.data = (unsigned long) sc->sc_num;
++	mod_timer(&sc->sc_tickto, jiffies + HZ);
++
++	return (0);
++
++fail:
++    if (sc->sc_cid >= 0)
++        crypto_unregister_all(sc->sc_cid);
++    if (sc->sc_irq != -1)
++        free_irq(sc->sc_irq, sc);
++    if (sc->sc_dma) {
++		/* Turn off DMA polling */
++		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++
++        pci_free_consistent(sc->sc_pcidev,
++				sizeof(*sc->sc_dma),
++                sc->sc_dma, sc->sc_dma_physaddr);
++	}
++    kfree(sc);
++	return (-ENXIO);
++}
++
++/*
++ * Detach an interface that successfully probed.
++ */
++static void
++hifn_remove(struct pci_dev *dev)
++{
++	struct hifn_softc *sc = pci_get_drvdata(dev);
++	unsigned long l_flags;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	KASSERT(sc != NULL, ("hifn_detach: null software carrier!"));
++
++	/* disable interrupts */
++	HIFN_LOCK(sc);
++	WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
++	HIFN_UNLOCK(sc);
++
++	/*XXX other resources */
++	del_timer_sync(&sc->sc_tickto);
++
++	/* Turn off DMA polling */
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++
++	crypto_unregister_all(sc->sc_cid);
++
++	free_irq(sc->sc_irq, sc);
++
++	pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
++                sc->sc_dma, sc->sc_dma_physaddr);
++}
++
++
++static int
++hifn_init_pubrng(struct hifn_softc *sc)
++{
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if ((sc->sc_flags & HIFN_IS_7811) == 0) {
++		/* Reset 7951 public key/rng engine */
++		WRITE_REG_1(sc, HIFN_1_PUB_RESET,
++		    READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET);
++
++		for (i = 0; i < 100; i++) {
++			DELAY(1000);
++			if ((READ_REG_1(sc, HIFN_1_PUB_RESET) &
++			    HIFN_PUBRST_RESET) == 0)
++				break;
++		}
++
++		if (i == 100) {
++			device_printf(sc->sc_dev, "public key init failed\n");
++			return (1);
++		}
++	}
++
++	/* Enable the rng, if available */
++#ifdef CONFIG_OCF_RANDOMHARVEST
++	if (sc->sc_flags & HIFN_HAS_RNG) {
++		if (sc->sc_flags & HIFN_IS_7811) {
++			u_int32_t r;
++			r = READ_REG_1(sc, HIFN_1_7811_RNGENA);
++			if (r & HIFN_7811_RNGENA_ENA) {
++				r &= ~HIFN_7811_RNGENA_ENA;
++				WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
++			}
++			WRITE_REG_1(sc, HIFN_1_7811_RNGCFG,
++			    HIFN_7811_RNGCFG_DEFL);
++			r |= HIFN_7811_RNGENA_ENA;
++			WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
++		} else
++			WRITE_REG_1(sc, HIFN_1_RNG_CONFIG,
++			    READ_REG_1(sc, HIFN_1_RNG_CONFIG) |
++			    HIFN_RNGCFG_ENA);
++
++		sc->sc_rngfirst = 1;
++		crypto_rregister(sc->sc_cid, hifn_read_random, sc);
++	}
++#endif
++
++	/* Enable public key engine, if available */
++	if (sc->sc_flags & HIFN_HAS_PUBLIC) {
++		WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
++		sc->sc_dmaier |= HIFN_DMAIER_PUBDONE;
++		WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
++#ifdef HIFN_VULCANDEV
++		sc->sc_pkdev = make_dev(&vulcanpk_cdevsw, 0, 
++					UID_ROOT, GID_WHEEL, 0666,
++					"vulcanpk");
++		sc->sc_pkdev->si_drv1 = sc;
++#endif
++	}
++
++	return (0);
++}
++
++#ifdef CONFIG_OCF_RANDOMHARVEST
++static int
++hifn_read_random(void *arg, u_int32_t *buf, int len)
++{
++	struct hifn_softc *sc = (struct hifn_softc *) arg;
++	u_int32_t sts;
++	int i, rc = 0;
++
++	if (len <= 0)
++		return rc;
++
++	if (sc->sc_flags & HIFN_IS_7811) {
++		/* ONLY VALID ON 7811!!!! */
++		for (i = 0; i < 5; i++) {
++			sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS);
++			if (sts & HIFN_7811_RNGSTS_UFL) {
++				device_printf(sc->sc_dev,
++					      "RNG underflow: disabling\n");
++				/* DAVIDM perhaps return -1 */
++				break;
++			}
++			if ((sts & HIFN_7811_RNGSTS_RDY) == 0)
++				break;
++
++			/*
++			 * There are at least two words in the RNG FIFO
++			 * at this point.
++			 */
++			if (rc < len)
++				buf[rc++] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
++			if (rc < len)
++				buf[rc++] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
++		}
++	} else
++		buf[rc++] = READ_REG_1(sc, HIFN_1_RNG_DATA);
++
++	/* NB: discard first data read */
++	if (sc->sc_rngfirst) {
++		sc->sc_rngfirst = 0;
++		rc = 0;
++	}
++
++	return(rc);
++}
++#endif /* CONFIG_OCF_RANDOMHARVEST */
++
++static void
++hifn_puc_wait(struct hifn_softc *sc)
++{
++	int i;
++	int reg = HIFN_0_PUCTRL;
++
++	if (sc->sc_flags & HIFN_IS_7956) {
++		reg = HIFN_0_PUCTRL2;
++	}
++
++	for (i = 5000; i > 0; i--) {
++		DELAY(1);
++		if (!(READ_REG_0(sc, reg) & HIFN_PUCTRL_RESET))
++			break;
++	}
++	if (!i)
++		device_printf(sc->sc_dev, "proc unit did not reset(0x%x)\n",
++				READ_REG_0(sc, HIFN_0_PUCTRL));
++}
++
++/*
++ * Reset the processing unit.
++ */
++static void
++hifn_reset_puc(struct hifn_softc *sc)
++{
++	/* Reset processing unit */
++	int reg = HIFN_0_PUCTRL;
++
++	if (sc->sc_flags & HIFN_IS_7956) {
++		reg = HIFN_0_PUCTRL2;
++	}
++	WRITE_REG_0(sc, reg, HIFN_PUCTRL_DMAENA);
++
++	hifn_puc_wait(sc);
++}
++
++/*
++ * Set the Retry and TRDY registers; note that we set them to
++ * zero because the 7811 locks up when forced to retry (section
++ * 3.6 of "Specification Update SU-0014-04".  Not clear if we
++ * should do this for all Hifn parts, but it doesn't seem to hurt.
++ */
++static void
++hifn_set_retry(struct hifn_softc *sc)
++{
++	DPRINTF("%s()\n", __FUNCTION__);
++	/* NB: RETRY only responds to 8-bit reads/writes */
++	pci_write_config_byte(sc->sc_pcidev, HIFN_RETRY_TIMEOUT, 0);
++	pci_write_config_dword(sc->sc_pcidev, HIFN_TRDY_TIMEOUT, 0);
++}
++
++/*
++ * Resets the board.  Values in the regesters are left as is
++ * from the reset (i.e. initial values are assigned elsewhere).
++ */
++static void
++hifn_reset_board(struct hifn_softc *sc, int full)
++{
++	u_int32_t reg;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++	/*
++	 * Set polling in the DMA configuration register to zero.  0x7 avoids
++	 * resetting the board and zeros out the other fields.
++	 */
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++
++	/*
++	 * Now that polling has been disabled, we have to wait 1 ms
++	 * before resetting the board.
++	 */
++	DELAY(1000);
++
++	/* Reset the DMA unit */
++	if (full) {
++		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
++		DELAY(1000);
++	} else {
++		WRITE_REG_1(sc, HIFN_1_DMA_CNFG,
++		    HIFN_DMACNFG_MODE | HIFN_DMACNFG_MSTRESET);
++		hifn_reset_puc(sc);
++	}
++
++	KASSERT(sc->sc_dma != NULL, ("hifn_reset_board: null DMA tag!"));
++	bzero(sc->sc_dma, sizeof(*sc->sc_dma));
++
++	/* Bring dma unit out of reset */
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++
++	hifn_puc_wait(sc);
++	hifn_set_retry(sc);
++
++	if (sc->sc_flags & HIFN_IS_7811) {
++		for (reg = 0; reg < 1000; reg++) {
++			if (READ_REG_1(sc, HIFN_1_7811_MIPSRST) &
++			    HIFN_MIPSRST_CRAMINIT)
++				break;
++			DELAY(1000);
++		}
++		if (reg == 1000)
++			device_printf(sc->sc_dev, ": cram init timeout\n");
++	} else {
++	  /* set up DMA configuration register #2 */
++	  /* turn off all PK and BAR0 swaps */
++	  WRITE_REG_1(sc, HIFN_1_DMA_CNFG2,
++		      (3 << HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT)|
++		      (3 << HIFN_DMACNFG2_INIT_READ_BURST_SHIFT)|
++		      (2 << HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT)|
++		      (2 << HIFN_DMACNFG2_TGT_READ_BURST_SHIFT));
++	}
++}
++
++static u_int32_t
++hifn_next_signature(u_int32_t a, u_int cnt)
++{
++	int i;
++	u_int32_t v;
++
++	for (i = 0; i < cnt; i++) {
++
++		/* get the parity */
++		v = a & 0x80080125;
++		v ^= v >> 16;
++		v ^= v >> 8;
++		v ^= v >> 4;
++		v ^= v >> 2;
++		v ^= v >> 1;
++
++		a = (v & 1) ^ (a << 1);
++	}
++
++	return a;
++}
++
++
++/*
++ * Checks to see if crypto is already enabled.  If crypto isn't enable,
++ * "hifn_enable_crypto" is called to enable it.  The check is important,
++ * as enabling crypto twice will lock the board.
++ */
++static int 
++hifn_enable_crypto(struct hifn_softc *sc)
++{
++	u_int32_t dmacfg, ramcfg, encl, addr, i;
++	char offtbl[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++					  0x00, 0x00, 0x00, 0x00 };
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	ramcfg = READ_REG_0(sc, HIFN_0_PUCNFG);
++	dmacfg = READ_REG_1(sc, HIFN_1_DMA_CNFG);
++
++	/*
++	 * The RAM config register's encrypt level bit needs to be set before
++	 * every read performed on the encryption level register.
++	 */
++	WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
++
++	encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
++
++	/*
++	 * Make sure we don't re-unlock.  Two unlocks kills chip until the
++	 * next reboot.
++	 */
++	if (encl == HIFN_PUSTAT_ENA_1 || encl == HIFN_PUSTAT_ENA_2) {
++#ifdef HIFN_DEBUG
++		if (hifn_debug)
++			device_printf(sc->sc_dev,
++			    "Strong crypto already enabled!\n");
++#endif
++		goto report;
++	}
++
++	if (encl != 0 && encl != HIFN_PUSTAT_ENA_0) {
++#ifdef HIFN_DEBUG
++		if (hifn_debug)
++			device_printf(sc->sc_dev,
++			      "Unknown encryption level 0x%x\n", encl);
++#endif
++		return 1;
++	}
++
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_UNLOCK |
++	    HIFN_DMACNFG_MSTRESET | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++	DELAY(1000);
++	addr = READ_REG_1(sc, HIFN_UNLOCK_SECRET1);
++	DELAY(1000);
++	WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, 0);
++	DELAY(1000);
++
++	for (i = 0; i <= 12; i++) {
++		addr = hifn_next_signature(addr, offtbl[i] + 0x101);
++		WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, addr);
++
++		DELAY(1000);
++	}
++
++	WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
++	encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
++
++#ifdef HIFN_DEBUG
++	if (hifn_debug) {
++		if (encl != HIFN_PUSTAT_ENA_1 && encl != HIFN_PUSTAT_ENA_2)
++			device_printf(sc->sc_dev, "Engine is permanently "
++				"locked until next system reset!\n");
++		else
++			device_printf(sc->sc_dev, "Engine enabled "
++				"successfully!\n");
++	}
++#endif
++
++report:
++	WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg);
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg);
++
++	switch (encl) {
++	case HIFN_PUSTAT_ENA_1:
++	case HIFN_PUSTAT_ENA_2:
++		break;
++	case HIFN_PUSTAT_ENA_0:
++	default:
++		device_printf(sc->sc_dev, "disabled\n");
++		break;
++	}
++
++	return 0;
++}
++
++/*
++ * Give initial values to the registers listed in the "Register Space"
++ * section of the HIFN Software Development reference manual.
++ */
++static void 
++hifn_init_pci_registers(struct hifn_softc *sc)
++{
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	/* write fixed values needed by the Initialization registers */
++	WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
++	WRITE_REG_0(sc, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
++	WRITE_REG_0(sc, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
++
++	/* write all 4 ring address registers */
++	WRITE_REG_1(sc, HIFN_1_DMA_CRAR, sc->sc_dma_physaddr +
++	    offsetof(struct hifn_dma, cmdr[0]));
++	WRITE_REG_1(sc, HIFN_1_DMA_SRAR, sc->sc_dma_physaddr +
++	    offsetof(struct hifn_dma, srcr[0]));
++	WRITE_REG_1(sc, HIFN_1_DMA_DRAR, sc->sc_dma_physaddr +
++	    offsetof(struct hifn_dma, dstr[0]));
++	WRITE_REG_1(sc, HIFN_1_DMA_RRAR, sc->sc_dma_physaddr +
++	    offsetof(struct hifn_dma, resr[0]));
++
++	DELAY(2000);
++
++	/* write status register */
++	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
++	    HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
++	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
++	    HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
++	    HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
++	    HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
++	    HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
++	    HIFN_DMACSR_S_WAIT |
++	    HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
++	    HIFN_DMACSR_C_WAIT |
++	    HIFN_DMACSR_ENGINE |
++	    ((sc->sc_flags & HIFN_HAS_PUBLIC) ?
++		HIFN_DMACSR_PUBDONE : 0) |
++	    ((sc->sc_flags & HIFN_IS_7811) ?
++		HIFN_DMACSR_ILLW | HIFN_DMACSR_ILLR : 0));
++
++	sc->sc_d_busy = sc->sc_r_busy = sc->sc_s_busy = sc->sc_c_busy = 0;
++	sc->sc_dmaier |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
++	    HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
++	    HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
++	    ((sc->sc_flags & HIFN_IS_7811) ?
++		HIFN_DMAIER_ILLW | HIFN_DMAIER_ILLR : 0);
++	sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
++	WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
++
++
++	if (sc->sc_flags & HIFN_IS_7956) {
++		u_int32_t pll;
++
++		WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
++		    HIFN_PUCNFG_TCALLPHASES |
++		    HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
++
++		/* turn off the clocks and insure bypass is set */
++		pll = READ_REG_1(sc, HIFN_1_PLL);
++		pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
++		  | HIFN_PLL_BP | HIFN_PLL_MBSET;
++		WRITE_REG_1(sc, HIFN_1_PLL, pll);
++		DELAY(10*1000);		/* 10ms */
++
++		/* change configuration */
++		pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
++		WRITE_REG_1(sc, HIFN_1_PLL, pll);
++		DELAY(10*1000);		/* 10ms */
++
++		/* disable bypass */
++		pll &= ~HIFN_PLL_BP;
++		WRITE_REG_1(sc, HIFN_1_PLL, pll);
++		/* enable clocks with new configuration */
++		pll |= HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL;
++		WRITE_REG_1(sc, HIFN_1_PLL, pll);
++	} else {
++		WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
++		    HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
++		    HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
++		    (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
++	}
++
++	WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
++	    ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
++	    ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
++}
++
++/*
++ * The maximum number of sessions supported by the card
++ * is dependent on the amount of context ram, which
++ * encryption algorithms are enabled, and how compression
++ * is configured.  This should be configured before this
++ * routine is called.
++ */
++static void
++hifn_sessions(struct hifn_softc *sc)
++{
++	u_int32_t pucnfg;
++	int ctxsize;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	pucnfg = READ_REG_0(sc, HIFN_0_PUCNFG);
++
++	if (pucnfg & HIFN_PUCNFG_COMPSING) {
++		if (pucnfg & HIFN_PUCNFG_ENCCNFG)
++			ctxsize = 128;
++		else
++			ctxsize = 512;
++		/*
++		 * 7955/7956 has internal context memory of 32K
++		 */
++		if (sc->sc_flags & HIFN_IS_7956)
++			sc->sc_maxses = 32768 / ctxsize;
++		else
++			sc->sc_maxses = 1 +
++			    ((sc->sc_ramsize - 32768) / ctxsize);
++	} else
++		sc->sc_maxses = sc->sc_ramsize / 16384;
++
++	if (sc->sc_maxses > 2048)
++		sc->sc_maxses = 2048;
++}
++
++/*
++ * Determine ram type (sram or dram).  Board should be just out of a reset
++ * state when this is called.
++ */
++static int
++hifn_ramtype(struct hifn_softc *sc)
++{
++	u_int8_t data[8], dataexpect[8];
++	int i;
++
++	for (i = 0; i < sizeof(data); i++)
++		data[i] = dataexpect[i] = 0x55;
++	if (hifn_writeramaddr(sc, 0, data))
++		return (-1);
++	if (hifn_readramaddr(sc, 0, data))
++		return (-1);
++	if (bcmp(data, dataexpect, sizeof(data)) != 0) {
++		sc->sc_drammodel = 1;
++		return (0);
++	}
++
++	for (i = 0; i < sizeof(data); i++)
++		data[i] = dataexpect[i] = 0xaa;
++	if (hifn_writeramaddr(sc, 0, data))
++		return (-1);
++	if (hifn_readramaddr(sc, 0, data))
++		return (-1);
++	if (bcmp(data, dataexpect, sizeof(data)) != 0) {
++		sc->sc_drammodel = 1;
++		return (0);
++	}
++
++	return (0);
++}
++
++#define	HIFN_SRAM_MAX		(32 << 20)
++#define	HIFN_SRAM_STEP_SIZE	16384
++#define	HIFN_SRAM_GRANULARITY	(HIFN_SRAM_MAX / HIFN_SRAM_STEP_SIZE)
++
++static int
++hifn_sramsize(struct hifn_softc *sc)
++{
++	u_int32_t a;
++	u_int8_t data[8];
++	u_int8_t dataexpect[sizeof(data)];
++	int32_t i;
++
++	for (i = 0; i < sizeof(data); i++)
++		data[i] = dataexpect[i] = i ^ 0x5a;
++
++	for (i = HIFN_SRAM_GRANULARITY - 1; i >= 0; i--) {
++		a = i * HIFN_SRAM_STEP_SIZE;
++		bcopy(&i, data, sizeof(i));
++		hifn_writeramaddr(sc, a, data);
++	}
++
++	for (i = 0; i < HIFN_SRAM_GRANULARITY; i++) {
++		a = i * HIFN_SRAM_STEP_SIZE;
++		bcopy(&i, dataexpect, sizeof(i));
++		if (hifn_readramaddr(sc, a, data) < 0)
++			return (0);
++		if (bcmp(data, dataexpect, sizeof(data)) != 0)
++			return (0);
++		sc->sc_ramsize = a + HIFN_SRAM_STEP_SIZE;
++	}
++
++	return (0);
++}
++
++/*
++ * XXX For dram boards, one should really try all of the
++ * HIFN_PUCNFG_DSZ_*'s.  This just assumes that PUCNFG
++ * is already set up correctly.
++ */
++static int
++hifn_dramsize(struct hifn_softc *sc)
++{
++	u_int32_t cnfg;
++
++	if (sc->sc_flags & HIFN_IS_7956) {
++		/*
++		 * 7955/7956 have a fixed internal ram of only 32K.
++		 */
++		sc->sc_ramsize = 32768;
++	} else {
++		cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
++		    HIFN_PUCNFG_DRAMMASK;
++		sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
++	}
++	return (0);
++}
++
++static void
++hifn_alloc_slot(struct hifn_softc *sc, int *cmdp, int *srcp, int *dstp, int *resp)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (dma->cmdi == HIFN_D_CMD_RSIZE) {
++		dma->cmdi = 0;
++		dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->cmdr[HIFN_D_CMD_RSIZE].l |= htole32(HIFN_D_VALID);
++		HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++	}
++	*cmdp = dma->cmdi++;
++	dma->cmdk = dma->cmdi;
++
++	if (dma->srci == HIFN_D_SRC_RSIZE) {
++		dma->srci = 0;
++		dma->srcr[HIFN_D_SRC_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->srcr[HIFN_D_SRC_RSIZE].l |= htole32(HIFN_D_VALID);
++		HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++	}
++	*srcp = dma->srci++;
++	dma->srck = dma->srci;
++
++	if (dma->dsti == HIFN_D_DST_RSIZE) {
++		dma->dsti = 0;
++		dma->dstr[HIFN_D_DST_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->dstr[HIFN_D_DST_RSIZE].l |= htole32(HIFN_D_VALID);
++		HIFN_DSTR_SYNC(sc, HIFN_D_DST_RSIZE,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++	}
++	*dstp = dma->dsti++;
++	dma->dstk = dma->dsti;
++
++	if (dma->resi == HIFN_D_RES_RSIZE) {
++		dma->resi = 0;
++		dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->resr[HIFN_D_RES_RSIZE].l |= htole32(HIFN_D_VALID);
++		HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++	}
++	*resp = dma->resi++;
++	dma->resk = dma->resi;
++}
++
++static int
++hifn_writeramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	hifn_base_command_t wc;
++	const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
++	int r, cmdi, resi, srci, dsti;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	wc.masks = htole16(3 << 13);
++	wc.session_num = htole16(addr >> 14);
++	wc.total_source_count = htole16(8);
++	wc.total_dest_count = htole16(addr & 0x3fff);
++
++	hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
++
++	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
++	    HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
++
++	/* build write command */
++	bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
++	*(hifn_base_command_t *)dma->command_bufs[cmdi] = wc;
++	bcopy(data, &dma->test_src, sizeof(dma->test_src));
++
++	dma->srcr[srci].p = htole32(sc->sc_dma_physaddr
++	    + offsetof(struct hifn_dma, test_src));
++	dma->dstr[dsti].p = htole32(sc->sc_dma_physaddr
++	    + offsetof(struct hifn_dma, test_dst));
++
++	dma->cmdr[cmdi].l = htole32(16 | masks);
++	dma->srcr[srci].l = htole32(8 | masks);
++	dma->dstr[dsti].l = htole32(4 | masks);
++	dma->resr[resi].l = htole32(4 | masks);
++
++	for (r = 10000; r >= 0; r--) {
++		DELAY(10);
++		if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
++			break;
++	}
++	if (r == 0) {
++		device_printf(sc->sc_dev, "writeramaddr -- "
++		    "result[%d](addr %d) still valid\n", resi, addr);
++		r = -1;
++		return (-1);
++	} else
++		r = 0;
++
++	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
++	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
++
++	return (r);
++}
++
++static int
++hifn_readramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	hifn_base_command_t rc;
++	const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
++	int r, cmdi, srci, dsti, resi;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	rc.masks = htole16(2 << 13);
++	rc.session_num = htole16(addr >> 14);
++	rc.total_source_count = htole16(addr & 0x3fff);
++	rc.total_dest_count = htole16(8);
++
++	hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
++
++	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
++	    HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
++
++	bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
++	*(hifn_base_command_t *)dma->command_bufs[cmdi] = rc;
++
++	dma->srcr[srci].p = htole32(sc->sc_dma_physaddr +
++	    offsetof(struct hifn_dma, test_src));
++	dma->test_src = 0;
++	dma->dstr[dsti].p =  htole32(sc->sc_dma_physaddr +
++	    offsetof(struct hifn_dma, test_dst));
++	dma->test_dst = 0;
++	dma->cmdr[cmdi].l = htole32(8 | masks);
++	dma->srcr[srci].l = htole32(8 | masks);
++	dma->dstr[dsti].l = htole32(8 | masks);
++	dma->resr[resi].l = htole32(HIFN_MAX_RESULT | masks);
++
++	for (r = 10000; r >= 0; r--) {
++		DELAY(10);
++		if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
++			break;
++	}
++	if (r == 0) {
++		device_printf(sc->sc_dev, "readramaddr -- "
++		    "result[%d](addr %d) still valid\n", resi, addr);
++		r = -1;
++	} else {
++		r = 0;
++		bcopy(&dma->test_dst, data, sizeof(dma->test_dst));
++	}
++
++	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
++	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
++
++	return (r);
++}
++
++/*
++ * Initialize the descriptor rings.
++ */
++static void 
++hifn_init_dma(struct hifn_softc *sc)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	hifn_set_retry(sc);
++
++	/* initialize static pointer values */
++	for (i = 0; i < HIFN_D_CMD_RSIZE; i++)
++		dma->cmdr[i].p = htole32(sc->sc_dma_physaddr +
++		    offsetof(struct hifn_dma, command_bufs[i][0]));
++	for (i = 0; i < HIFN_D_RES_RSIZE; i++)
++		dma->resr[i].p = htole32(sc->sc_dma_physaddr +
++		    offsetof(struct hifn_dma, result_bufs[i][0]));
++
++	dma->cmdr[HIFN_D_CMD_RSIZE].p =
++	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, cmdr[0]));
++	dma->srcr[HIFN_D_SRC_RSIZE].p =
++	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, srcr[0]));
++	dma->dstr[HIFN_D_DST_RSIZE].p =
++	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, dstr[0]));
++	dma->resr[HIFN_D_RES_RSIZE].p =
++	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, resr[0]));
++
++	dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
++	dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
++	dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
++}
++
++/*
++ * Writes out the raw command buffer space.  Returns the
++ * command buffer size.
++ */
++static u_int
++hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
++{
++	struct hifn_softc *sc = NULL;
++	u_int8_t *buf_pos;
++	hifn_base_command_t *base_cmd;
++	hifn_mac_command_t *mac_cmd;
++	hifn_crypt_command_t *cry_cmd;
++	int using_mac, using_crypt, len, ivlen;
++	u_int32_t dlen, slen;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	buf_pos = buf;
++	using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC;
++	using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT;
++
++	base_cmd = (hifn_base_command_t *)buf_pos;
++	base_cmd->masks = htole16(cmd->base_masks);
++	slen = cmd->src_mapsize;
++	if (cmd->sloplen)
++		dlen = cmd->dst_mapsize - cmd->sloplen + sizeof(u_int32_t);
++	else
++		dlen = cmd->dst_mapsize;
++	base_cmd->total_source_count = htole16(slen & HIFN_BASE_CMD_LENMASK_LO);
++	base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
++	dlen >>= 16;
++	slen >>= 16;
++	base_cmd->session_num = htole16(
++	    ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
++	    ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
++	buf_pos += sizeof(hifn_base_command_t);
++
++	if (using_mac) {
++		mac_cmd = (hifn_mac_command_t *)buf_pos;
++		dlen = cmd->maccrd->crd_len;
++		mac_cmd->source_count = htole16(dlen & 0xffff);
++		dlen >>= 16;
++		mac_cmd->masks = htole16(cmd->mac_masks |
++		    ((dlen << HIFN_MAC_CMD_SRCLEN_S) & HIFN_MAC_CMD_SRCLEN_M));
++		mac_cmd->header_skip = htole16(cmd->maccrd->crd_skip);
++		mac_cmd->reserved = 0;
++		buf_pos += sizeof(hifn_mac_command_t);
++	}
++
++	if (using_crypt) {
++		cry_cmd = (hifn_crypt_command_t *)buf_pos;
++		dlen = cmd->enccrd->crd_len;
++		cry_cmd->source_count = htole16(dlen & 0xffff);
++		dlen >>= 16;
++		cry_cmd->masks = htole16(cmd->cry_masks |
++		    ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) & HIFN_CRYPT_CMD_SRCLEN_M));
++		cry_cmd->header_skip = htole16(cmd->enccrd->crd_skip);
++		cry_cmd->reserved = 0;
++		buf_pos += sizeof(hifn_crypt_command_t);
++	}
++
++	if (using_mac && cmd->mac_masks & HIFN_MAC_CMD_NEW_KEY) {
++		bcopy(cmd->mac, buf_pos, HIFN_MAC_KEY_LENGTH);
++		buf_pos += HIFN_MAC_KEY_LENGTH;
++	}
++
++	if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_KEY) {
++		switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
++		case HIFN_CRYPT_CMD_ALG_3DES:
++			bcopy(cmd->ck, buf_pos, HIFN_3DES_KEY_LENGTH);
++			buf_pos += HIFN_3DES_KEY_LENGTH;
++			break;
++		case HIFN_CRYPT_CMD_ALG_DES:
++			bcopy(cmd->ck, buf_pos, HIFN_DES_KEY_LENGTH);
++			buf_pos += HIFN_DES_KEY_LENGTH;
++			break;
++		case HIFN_CRYPT_CMD_ALG_RC4:
++			len = 256;
++			do {
++				int clen;
++
++				clen = MIN(cmd->cklen, len);
++				bcopy(cmd->ck, buf_pos, clen);
++				len -= clen;
++				buf_pos += clen;
++			} while (len > 0);
++			bzero(buf_pos, 4);
++			buf_pos += 4;
++			break;
++		case HIFN_CRYPT_CMD_ALG_AES:
++			/*
++			 * AES keys are variable 128, 192 and
++			 * 256 bits (16, 24 and 32 bytes).
++			 */
++			bcopy(cmd->ck, buf_pos, cmd->cklen);
++			buf_pos += cmd->cklen;
++			break;
++		}
++	}
++
++	if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) {
++		switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
++		case HIFN_CRYPT_CMD_ALG_AES:
++			ivlen = HIFN_AES_IV_LENGTH;
++			break;
++		default:
++			ivlen = HIFN_IV_LENGTH;
++			break;
++		}
++		bcopy(cmd->iv, buf_pos, ivlen);
++		buf_pos += ivlen;
++	}
++
++	if ((cmd->base_masks & (HIFN_BASE_CMD_MAC|HIFN_BASE_CMD_CRYPT)) == 0) {
++		bzero(buf_pos, 8);
++		buf_pos += 8;
++	}
++
++	return (buf_pos - buf);
++}
++
++static int
++hifn_dmamap_aligned(struct hifn_operand *op)
++{
++	struct hifn_softc *sc = NULL;
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	for (i = 0; i < op->nsegs; i++) {
++		if (op->segs[i].ds_addr & 3)
++			return (0);
++		if ((i != (op->nsegs - 1)) && (op->segs[i].ds_len & 3))
++			return (0);
++	}
++	return (1);
++}
++
++static __inline int
++hifn_dmamap_dstwrap(struct hifn_softc *sc, int idx)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++
++	if (++idx == HIFN_D_DST_RSIZE) {
++		dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
++		    HIFN_D_MASKDONEIRQ);
++		HIFN_DSTR_SYNC(sc, idx,
++		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++		idx = 0;
++	}
++	return (idx);
++}
++
++static int
++hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	struct hifn_operand *dst = &cmd->dst;
++	u_int32_t p, l;
++	int idx, used = 0, i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	idx = dma->dsti;
++	for (i = 0; i < dst->nsegs - 1; i++) {
++		dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
++		dma->dstr[idx].l = htole32(HIFN_D_MASKDONEIRQ | dst->segs[i].ds_len);
++		wmb();
++		dma->dstr[idx].l |= htole32(HIFN_D_VALID);
++		HIFN_DSTR_SYNC(sc, idx,
++		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++		used++;
++
++		idx = hifn_dmamap_dstwrap(sc, idx);
++	}
++
++	if (cmd->sloplen == 0) {
++		p = dst->segs[i].ds_addr;
++		l = HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
++		    dst->segs[i].ds_len;
++	} else {
++		p = sc->sc_dma_physaddr +
++		    offsetof(struct hifn_dma, slop[cmd->slopidx]);
++		l = HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
++		    sizeof(u_int32_t);
++
++		if ((dst->segs[i].ds_len - cmd->sloplen) != 0) {
++			dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
++			dma->dstr[idx].l = htole32(HIFN_D_MASKDONEIRQ |
++			    (dst->segs[i].ds_len - cmd->sloplen));
++			wmb();
++			dma->dstr[idx].l |= htole32(HIFN_D_VALID);
++			HIFN_DSTR_SYNC(sc, idx,
++			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++			used++;
++
++			idx = hifn_dmamap_dstwrap(sc, idx);
++		}
++	}
++	dma->dstr[idx].p = htole32(p);
++	dma->dstr[idx].l = htole32(l);
++	wmb();
++	dma->dstr[idx].l |= htole32(HIFN_D_VALID);
++	HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++	used++;
++
++	idx = hifn_dmamap_dstwrap(sc, idx);
++
++	dma->dsti = idx;
++	dma->dstu += used;
++	return (idx);
++}
++
++static __inline int
++hifn_dmamap_srcwrap(struct hifn_softc *sc, int idx)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++
++	if (++idx == HIFN_D_SRC_RSIZE) {
++		dma->srcr[idx].l = htole32(HIFN_D_VALID |
++		    HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
++		HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++		idx = 0;
++	}
++	return (idx);
++}
++
++static int
++hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	struct hifn_operand *src = &cmd->src;
++	int idx, i;
++	u_int32_t last = 0;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	idx = dma->srci;
++	for (i = 0; i < src->nsegs; i++) {
++		if (i == src->nsegs - 1)
++			last = HIFN_D_LAST;
++
++		dma->srcr[idx].p = htole32(src->segs[i].ds_addr);
++		dma->srcr[idx].l = htole32(src->segs[i].ds_len |
++		    HIFN_D_MASKDONEIRQ | last);
++		wmb();
++		dma->srcr[idx].l |= htole32(HIFN_D_VALID);
++		HIFN_SRCR_SYNC(sc, idx,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++
++		idx = hifn_dmamap_srcwrap(sc, idx);
++	}
++	dma->srci = idx;
++	dma->srcu += src->nsegs;
++	return (idx);
++} 
++
++
++static int 
++hifn_crypto(
++	struct hifn_softc *sc,
++	struct hifn_command *cmd,
++	struct cryptop *crp,
++	int hint)
++{
++	struct	hifn_dma *dma = sc->sc_dma;
++	u_int32_t cmdlen, csr;
++	int cmdi, resi, err = 0;
++	unsigned long l_flags;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	/*
++	 * need 1 cmd, and 1 res
++	 *
++	 * NB: check this first since it's easy.
++	 */
++	HIFN_LOCK(sc);
++	if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE ||
++	    (dma->resu + 1) > HIFN_D_RES_RSIZE) {
++#ifdef HIFN_DEBUG
++		if (hifn_debug) {
++			device_printf(sc->sc_dev,
++				"cmd/result exhaustion, cmdu %u resu %u\n",
++				dma->cmdu, dma->resu);
++		}
++#endif
++		hifnstats.hst_nomem_cr++;
++		sc->sc_needwakeup |= CRYPTO_SYMQ;
++		HIFN_UNLOCK(sc);
++		return (ERESTART);
++	}
++
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		if (pci_map_skb(sc, &cmd->src, cmd->src_skb)) {
++			hifnstats.hst_nomem_load++;
++			err = ENOMEM;
++			goto err_srcmap1;
++		}
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		if (pci_map_uio(sc, &cmd->src, cmd->src_io)) {
++			hifnstats.hst_nomem_load++;
++			err = ENOMEM;
++			goto err_srcmap1;
++		}
++	} else {
++		if (pci_map_buf(sc, &cmd->src, cmd->src_buf, crp->crp_ilen)) {
++			hifnstats.hst_nomem_load++;
++			err = ENOMEM;
++			goto err_srcmap1;
++		}
++	}
++
++	if (hifn_dmamap_aligned(&cmd->src)) {
++		cmd->sloplen = cmd->src_mapsize & 3;
++		cmd->dst = cmd->src;
++	} else {
++		if (crp->crp_flags & CRYPTO_F_IOV) {
++			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++			err = EINVAL;
++			goto err_srcmap;
++		} else if (crp->crp_flags & CRYPTO_F_SKBUF) {
++#ifdef NOTYET
++			int totlen, len;
++			struct mbuf *m, *m0, *mlast;
++
++			KASSERT(cmd->dst_m == cmd->src_m,
++				("hifn_crypto: dst_m initialized improperly"));
++			hifnstats.hst_unaligned++;
++			/*
++			 * Source is not aligned on a longword boundary.
++			 * Copy the data to insure alignment.  If we fail
++			 * to allocate mbufs or clusters while doing this
++			 * we return ERESTART so the operation is requeued
++			 * at the crypto later, but only if there are
++			 * ops already posted to the hardware; otherwise we
++			 * have no guarantee that we'll be re-entered.
++			 */
++			totlen = cmd->src_mapsize;
++			if (cmd->src_m->m_flags & M_PKTHDR) {
++				len = MHLEN;
++				MGETHDR(m0, M_DONTWAIT, MT_DATA);
++				if (m0 && !m_dup_pkthdr(m0, cmd->src_m, M_DONTWAIT)) {
++					m_free(m0);
++					m0 = NULL;
++				}
++			} else {
++				len = MLEN;
++				MGET(m0, M_DONTWAIT, MT_DATA);
++			}
++			if (m0 == NULL) {
++				hifnstats.hst_nomem_mbuf++;
++				err = dma->cmdu ? ERESTART : ENOMEM;
++				goto err_srcmap;
++			}
++			if (totlen >= MINCLSIZE) {
++				MCLGET(m0, M_DONTWAIT);
++				if ((m0->m_flags & M_EXT) == 0) {
++					hifnstats.hst_nomem_mcl++;
++					err = dma->cmdu ? ERESTART : ENOMEM;
++					m_freem(m0);
++					goto err_srcmap;
++				}
++				len = MCLBYTES;
++			}
++			totlen -= len;
++			m0->m_pkthdr.len = m0->m_len = len;
++			mlast = m0;
++
++			while (totlen > 0) {
++				MGET(m, M_DONTWAIT, MT_DATA);
++				if (m == NULL) {
++					hifnstats.hst_nomem_mbuf++;
++					err = dma->cmdu ? ERESTART : ENOMEM;
++					m_freem(m0);
++					goto err_srcmap;
++				}
++				len = MLEN;
++				if (totlen >= MINCLSIZE) {
++					MCLGET(m, M_DONTWAIT);
++					if ((m->m_flags & M_EXT) == 0) {
++						hifnstats.hst_nomem_mcl++;
++						err = dma->cmdu ? ERESTART : ENOMEM;
++						mlast->m_next = m;
++						m_freem(m0);
++						goto err_srcmap;
++					}
++					len = MCLBYTES;
++				}
++
++				m->m_len = len;
++				m0->m_pkthdr.len += len;
++				totlen -= len;
++
++				mlast->m_next = m;
++				mlast = m;
++			}
++			cmd->dst_m = m0;
++#else
++			device_printf(sc->sc_dev,
++					"%s,%d: CRYPTO_F_SKBUF unaligned not implemented\n",
++					__FILE__, __LINE__);
++			err = EINVAL;
++			goto err_srcmap;
++#endif
++		} else {
++			device_printf(sc->sc_dev,
++					"%s,%d: unaligned contig buffers not implemented\n",
++					__FILE__, __LINE__);
++			err = EINVAL;
++			goto err_srcmap;
++		}
++	}
++
++	if (cmd->dst_map == NULL) {
++		if (crp->crp_flags & CRYPTO_F_SKBUF) {
++			if (pci_map_skb(sc, &cmd->dst, cmd->dst_skb)) {
++				hifnstats.hst_nomem_map++;
++				err = ENOMEM;
++				goto err_dstmap1;
++			}
++		} else if (crp->crp_flags & CRYPTO_F_IOV) {
++			if (pci_map_uio(sc, &cmd->dst, cmd->dst_io)) {
++				hifnstats.hst_nomem_load++;
++				err = ENOMEM;
++				goto err_dstmap1;
++			}
++		} else {
++			if (pci_map_buf(sc, &cmd->dst, cmd->dst_buf, crp->crp_ilen)) {
++				hifnstats.hst_nomem_load++;
++				err = ENOMEM;
++				goto err_dstmap1;
++			}
++		}
++	}
++
++#ifdef HIFN_DEBUG
++	if (hifn_debug) {
++		device_printf(sc->sc_dev,
++		    "Entering cmd: stat %8x ien %8x u %d/%d/%d/%d n %d/%d\n",
++		    READ_REG_1(sc, HIFN_1_DMA_CSR),
++		    READ_REG_1(sc, HIFN_1_DMA_IER),
++		    dma->cmdu, dma->srcu, dma->dstu, dma->resu,
++		    cmd->src_nsegs, cmd->dst_nsegs);
++	}
++#endif
++
++#if 0
++	if (cmd->src_map == cmd->dst_map) {
++		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
++		    BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
++	} else {
++		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
++		    BUS_DMASYNC_PREWRITE);
++		bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
++		    BUS_DMASYNC_PREREAD);
++	}
++#endif
++
++	/*
++	 * need N src, and N dst
++	 */
++	if ((dma->srcu + cmd->src_nsegs) > HIFN_D_SRC_RSIZE ||
++	    (dma->dstu + cmd->dst_nsegs + 1) > HIFN_D_DST_RSIZE) {
++#ifdef HIFN_DEBUG
++		if (hifn_debug) {
++			device_printf(sc->sc_dev,
++				"src/dst exhaustion, srcu %u+%u dstu %u+%u\n",
++				dma->srcu, cmd->src_nsegs,
++				dma->dstu, cmd->dst_nsegs);
++		}
++#endif
++		hifnstats.hst_nomem_sd++;
++		err = ERESTART;
++		goto err_dstmap;
++	}
++
++	if (dma->cmdi == HIFN_D_CMD_RSIZE) {
++		dma->cmdi = 0;
++		dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->cmdr[HIFN_D_CMD_RSIZE].l |= htole32(HIFN_D_VALID);
++		HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
++		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++	}
++	cmdi = dma->cmdi++;
++	cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]);
++	HIFN_CMD_SYNC(sc, cmdi, BUS_DMASYNC_PREWRITE);
++
++	/* .p for command/result already set */
++	dma->cmdr[cmdi].l = htole32(cmdlen | HIFN_D_LAST |
++	    HIFN_D_MASKDONEIRQ);
++	wmb();
++	dma->cmdr[cmdi].l |= htole32(HIFN_D_VALID);
++	HIFN_CMDR_SYNC(sc, cmdi,
++	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
++	dma->cmdu++;
++
++	/*
++	 * We don't worry about missing an interrupt (which a "command wait"
++	 * interrupt salvages us from), unless there is more than one command
++	 * in the queue.
++	 */
++	if (dma->cmdu > 1) {
++		sc->sc_dmaier |= HIFN_DMAIER_C_WAIT;
++		WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
++	}
++
++	hifnstats.hst_ipackets++;
++	hifnstats.hst_ibytes += cmd->src_mapsize;
++
++	hifn_dmamap_load_src(sc, cmd);
++
++	/*
++	 * Unlike other descriptors, we don't mask done interrupt from
++	 * result descriptor.
++	 */
++#ifdef HIFN_DEBUG
++	if (hifn_debug)
++		device_printf(sc->sc_dev, "load res\n");
++#endif
++	if (dma->resi == HIFN_D_RES_RSIZE) {
++		dma->resi = 0;
++		dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->resr[HIFN_D_RES_RSIZE].l |= htole32(HIFN_D_VALID);
++		HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
++		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++	}
++	resi = dma->resi++;
++	KASSERT(dma->hifn_commands[resi] == NULL,
++		("hifn_crypto: command slot %u busy", resi));
++	dma->hifn_commands[resi] = cmd;
++	HIFN_RES_SYNC(sc, resi, BUS_DMASYNC_PREREAD);
++	if ((hint & CRYPTO_HINT_MORE) && sc->sc_curbatch < hifn_maxbatch) {
++		dma->resr[resi].l = htole32(HIFN_MAX_RESULT |
++		    HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
++		wmb();
++		dma->resr[resi].l |= htole32(HIFN_D_VALID);
++		sc->sc_curbatch++;
++		if (sc->sc_curbatch > hifnstats.hst_maxbatch)
++			hifnstats.hst_maxbatch = sc->sc_curbatch;
++		hifnstats.hst_totbatch++;
++	} else {
++		dma->resr[resi].l = htole32(HIFN_MAX_RESULT | HIFN_D_LAST);
++		wmb();
++		dma->resr[resi].l |= htole32(HIFN_D_VALID);
++		sc->sc_curbatch = 0;
++	}
++	HIFN_RESR_SYNC(sc, resi,
++	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++	dma->resu++;
++
++	if (cmd->sloplen)
++		cmd->slopidx = resi;
++
++	hifn_dmamap_load_dst(sc, cmd);
++
++	csr = 0;
++	if (sc->sc_c_busy == 0) {
++		csr |= HIFN_DMACSR_C_CTRL_ENA;
++		sc->sc_c_busy = 1;
++	}
++	if (sc->sc_s_busy == 0) {
++		csr |= HIFN_DMACSR_S_CTRL_ENA;
++		sc->sc_s_busy = 1;
++	}
++	if (sc->sc_r_busy == 0) {
++		csr |= HIFN_DMACSR_R_CTRL_ENA;
++		sc->sc_r_busy = 1;
++	}
++	if (sc->sc_d_busy == 0) {
++		csr |= HIFN_DMACSR_D_CTRL_ENA;
++		sc->sc_d_busy = 1;
++	}
++	if (csr)
++		WRITE_REG_1(sc, HIFN_1_DMA_CSR, csr);
++
++#ifdef HIFN_DEBUG
++	if (hifn_debug) {
++		device_printf(sc->sc_dev, "command: stat %8x ier %8x\n",
++		    READ_REG_1(sc, HIFN_1_DMA_CSR),
++		    READ_REG_1(sc, HIFN_1_DMA_IER));
++	}
++#endif
++
++	sc->sc_active = 5;
++	HIFN_UNLOCK(sc);
++	KASSERT(err == 0, ("hifn_crypto: success with error %u", err));
++	return (err);		/* success */
++
++err_dstmap:
++	if (cmd->src_map != cmd->dst_map)
++		pci_unmap_buf(sc, &cmd->dst);
++err_dstmap1:
++err_srcmap:
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		if (cmd->src_skb != cmd->dst_skb)
++#ifdef NOTYET
++			m_freem(cmd->dst_m);
++#else
++			device_printf(sc->sc_dev,
++					"%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
++					__FILE__, __LINE__);
++#endif
++	}
++	pci_unmap_buf(sc, &cmd->src);
++err_srcmap1:
++	HIFN_UNLOCK(sc);
++	return (err);
++}
++
++static void
++hifn_tick(unsigned long arg)
++{
++	struct hifn_softc *sc;
++	unsigned long l_flags;
++
++	if (arg >= HIFN_MAX_CHIPS)
++		return;
++	sc = hifn_chip_idx[arg];
++	if (!sc)
++		return;
++
++	HIFN_LOCK(sc);
++	if (sc->sc_active == 0) {
++		struct hifn_dma *dma = sc->sc_dma;
++		u_int32_t r = 0;
++
++		if (dma->cmdu == 0 && sc->sc_c_busy) {
++			sc->sc_c_busy = 0;
++			r |= HIFN_DMACSR_C_CTRL_DIS;
++		}
++		if (dma->srcu == 0 && sc->sc_s_busy) {
++			sc->sc_s_busy = 0;
++			r |= HIFN_DMACSR_S_CTRL_DIS;
++		}
++		if (dma->dstu == 0 && sc->sc_d_busy) {
++			sc->sc_d_busy = 0;
++			r |= HIFN_DMACSR_D_CTRL_DIS;
++		}
++		if (dma->resu == 0 && sc->sc_r_busy) {
++			sc->sc_r_busy = 0;
++			r |= HIFN_DMACSR_R_CTRL_DIS;
++		}
++		if (r)
++			WRITE_REG_1(sc, HIFN_1_DMA_CSR, r);
++	} else
++		sc->sc_active--;
++	HIFN_UNLOCK(sc);
++	mod_timer(&sc->sc_tickto, jiffies + HZ);
++}
++
++static irqreturn_t
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++hifn_intr(int irq, void *arg)
++#else
++hifn_intr(int irq, void *arg, struct pt_regs *regs)
++#endif
++{
++	struct hifn_softc *sc = arg;
++	struct hifn_dma *dma;
++	u_int32_t dmacsr, restart;
++	int i, u;
++	unsigned long l_flags;
++
++	dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
++
++	/* Nothing in the DMA unit interrupted */
++	if ((dmacsr & sc->sc_dmaier) == 0)
++		return IRQ_NONE;
++
++	HIFN_LOCK(sc);
++
++	dma = sc->sc_dma;
++
++#ifdef HIFN_DEBUG
++	if (hifn_debug) {
++		device_printf(sc->sc_dev,
++		    "irq: stat %08x ien %08x damier %08x i %d/%d/%d/%d k %d/%d/%d/%d u %d/%d/%d/%d\n",
++		    dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), sc->sc_dmaier,
++		    dma->cmdi, dma->srci, dma->dsti, dma->resi,
++		    dma->cmdk, dma->srck, dma->dstk, dma->resk,
++		    dma->cmdu, dma->srcu, dma->dstu, dma->resu);
++	}
++#endif
++
++	WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier);
++
++	if ((sc->sc_flags & HIFN_HAS_PUBLIC) &&
++	    (dmacsr & HIFN_DMACSR_PUBDONE))
++		WRITE_REG_1(sc, HIFN_1_PUB_STATUS,
++		    READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
++
++	restart = dmacsr & (HIFN_DMACSR_D_OVER | HIFN_DMACSR_R_OVER);
++	if (restart)
++		device_printf(sc->sc_dev, "overrun %x\n", dmacsr);
++
++	if (sc->sc_flags & HIFN_IS_7811) {
++		if (dmacsr & HIFN_DMACSR_ILLR)
++			device_printf(sc->sc_dev, "illegal read\n");
++		if (dmacsr & HIFN_DMACSR_ILLW)
++			device_printf(sc->sc_dev, "illegal write\n");
++	}
++
++	restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
++	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
++	if (restart) {
++		device_printf(sc->sc_dev, "abort, resetting.\n");
++		hifnstats.hst_abort++;
++		hifn_abort(sc);
++		HIFN_UNLOCK(sc);
++		return IRQ_HANDLED;
++	}
++
++	if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
++		/*
++		 * If no slots to process and we receive a "waiting on
++		 * command" interrupt, we disable the "waiting on command"
++		 * (by clearing it).
++		 */
++		sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
++		WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
++	}
++
++	/* clear the rings */
++	i = dma->resk; u = dma->resu;
++	while (u != 0) {
++		HIFN_RESR_SYNC(sc, i,
++		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
++		if (dma->resr[i].l & htole32(HIFN_D_VALID)) {
++			HIFN_RESR_SYNC(sc, i,
++			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++			break;
++		}
++
++		if (i != HIFN_D_RES_RSIZE) {
++			struct hifn_command *cmd;
++			u_int8_t *macbuf = NULL;
++
++			HIFN_RES_SYNC(sc, i, BUS_DMASYNC_POSTREAD);
++			cmd = dma->hifn_commands[i];
++			KASSERT(cmd != NULL,
++				("hifn_intr: null command slot %u", i));
++			dma->hifn_commands[i] = NULL;
++
++			if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
++				macbuf = dma->result_bufs[i];
++				macbuf += 12;
++			}
++
++			hifn_callback(sc, cmd, macbuf);
++			hifnstats.hst_opackets++;
++			u--;
++		}
++
++		if (++i == (HIFN_D_RES_RSIZE + 1))
++			i = 0;
++	}
++	dma->resk = i; dma->resu = u;
++
++	i = dma->srck; u = dma->srcu;
++	while (u != 0) {
++		if (i == HIFN_D_SRC_RSIZE)
++			i = 0;
++		HIFN_SRCR_SYNC(sc, i,
++		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
++		if (dma->srcr[i].l & htole32(HIFN_D_VALID)) {
++			HIFN_SRCR_SYNC(sc, i,
++			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++			break;
++		}
++		i++, u--;
++	}
++	dma->srck = i; dma->srcu = u;
++
++	i = dma->cmdk; u = dma->cmdu;
++	while (u != 0) {
++		HIFN_CMDR_SYNC(sc, i,
++		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
++		if (dma->cmdr[i].l & htole32(HIFN_D_VALID)) {
++			HIFN_CMDR_SYNC(sc, i,
++			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++			break;
++		}
++		if (i != HIFN_D_CMD_RSIZE) {
++			u--;
++			HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE);
++		}
++		if (++i == (HIFN_D_CMD_RSIZE + 1))
++			i = 0;
++	}
++	dma->cmdk = i; dma->cmdu = u;
++
++	HIFN_UNLOCK(sc);
++
++	if (sc->sc_needwakeup) {		/* XXX check high watermark */
++		int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
++#ifdef HIFN_DEBUG
++		if (hifn_debug)
++			device_printf(sc->sc_dev,
++				"wakeup crypto (%x) u %d/%d/%d/%d\n",
++				sc->sc_needwakeup,
++				dma->cmdu, dma->srcu, dma->dstu, dma->resu);
++#endif
++		sc->sc_needwakeup &= ~wakeup;
++		crypto_unblock(sc->sc_cid, wakeup);
++	}
++
++	return IRQ_HANDLED;
++}
++
++/*
++ * Allocate a new 'session' and return an encoded session id.  'sidp'
++ * contains our registration id, and should contain an encoded session
++ * id on successful allocation.
++ */
++static int
++hifn_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
++{
++	struct hifn_softc *sc = device_get_softc(dev);
++	struct cryptoini *c;
++	int mac = 0, cry = 0, sesn;
++	struct hifn_session *ses = NULL;
++	unsigned long l_flags;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	KASSERT(sc != NULL, ("hifn_newsession: null softc"));
++	if (sidp == NULL || cri == NULL || sc == NULL) {
++		DPRINTF("%s,%d: %s - EINVAL\n", __FILE__, __LINE__, __FUNCTION__);
++		return (EINVAL);
++	}
++
++	HIFN_LOCK(sc);
++	if (sc->sc_sessions == NULL) {
++		ses = sc->sc_sessions = (struct hifn_session *)kmalloc(sizeof(*ses),
++				SLAB_ATOMIC);
++		if (ses == NULL) {
++			HIFN_UNLOCK(sc);
++			return (ENOMEM);
++		}
++		sesn = 0;
++		sc->sc_nsessions = 1;
++	} else {
++		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
++			if (!sc->sc_sessions[sesn].hs_used) {
++				ses = &sc->sc_sessions[sesn];
++				break;
++			}
++		}
++
++		if (ses == NULL) {
++			sesn = sc->sc_nsessions;
++			ses = (struct hifn_session *)kmalloc((sesn + 1) * sizeof(*ses),
++					SLAB_ATOMIC);
++			if (ses == NULL) {
++				HIFN_UNLOCK(sc);
++				return (ENOMEM);
++			}
++			bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
++			bzero(sc->sc_sessions, sesn * sizeof(*ses));
++			kfree(sc->sc_sessions);
++			sc->sc_sessions = ses;
++			ses = &sc->sc_sessions[sesn];
++			sc->sc_nsessions++;
++		}
++	}
++	HIFN_UNLOCK(sc);
++
++	bzero(ses, sizeof(*ses));
++	ses->hs_used = 1;
++
++	for (c = cri; c != NULL; c = c->cri_next) {
++		switch (c->cri_alg) {
++		case CRYPTO_MD5:
++		case CRYPTO_SHA1:
++		case CRYPTO_MD5_HMAC:
++		case CRYPTO_SHA1_HMAC:
++			if (mac) {
++				DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++				return (EINVAL);
++			}
++			mac = 1;
++			ses->hs_mlen = c->cri_mlen;
++			if (ses->hs_mlen == 0) {
++				switch (c->cri_alg) {
++				case CRYPTO_MD5:
++				case CRYPTO_MD5_HMAC:
++					ses->hs_mlen = 16;
++					break;
++				case CRYPTO_SHA1:
++				case CRYPTO_SHA1_HMAC:
++					ses->hs_mlen = 20;
++					break;
++				}
++			}
++			break;
++		case CRYPTO_DES_CBC:
++		case CRYPTO_3DES_CBC:
++		case CRYPTO_AES_CBC:
++			/* XXX this may read fewer, does it matter? */
++			read_random(ses->hs_iv,
++				c->cri_alg == CRYPTO_AES_CBC ?
++					HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
++			/*FALLTHROUGH*/
++		case CRYPTO_ARC4:
++			if (cry) {
++				DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++				return (EINVAL);
++			}
++			cry = 1;
++			break;
++		default:
++			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++			return (EINVAL);
++		}
++	}
++	if (mac == 0 && cry == 0) {
++		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++		return (EINVAL);
++	}
++
++	*sidp = HIFN_SID(device_get_unit(sc->sc_dev), sesn);
++
++	return (0);
++}
++
++/*
++ * Deallocate a session.
++ * XXX this routine should run a zero'd mac/encrypt key into context ram.
++ * XXX to blow away any keys already stored there.
++ */
++static int
++hifn_freesession(device_t dev, u_int64_t tid)
++{
++	struct hifn_softc *sc = device_get_softc(dev);
++	int session, error;
++	u_int32_t sid = CRYPTO_SESID2LID(tid);
++	unsigned long l_flags;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	KASSERT(sc != NULL, ("hifn_freesession: null softc"));
++	if (sc == NULL) {
++		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++		return (EINVAL);
++	}
++
++	HIFN_LOCK(sc);
++	session = HIFN_SESSION(sid);
++	if (session < sc->sc_nsessions) {
++		bzero(&sc->sc_sessions[session], sizeof(struct hifn_session));
++		error = 0;
++	} else {
++		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++		error = EINVAL;
++	}
++	HIFN_UNLOCK(sc);
++
++	return (error);
++}
++
++static int
++hifn_process(device_t dev, struct cryptop *crp, int hint)
++{
++	struct hifn_softc *sc = device_get_softc(dev);
++	struct hifn_command *cmd = NULL;
++	int session, err, ivlen;
++	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (crp == NULL || crp->crp_callback == NULL) {
++		hifnstats.hst_invalid++;
++		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++		return (EINVAL);
++	}
++	session = HIFN_SESSION(crp->crp_sid);
++
++	if (sc == NULL || session >= sc->sc_nsessions) {
++		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++		err = EINVAL;
++		goto errout;
++	}
++
++	cmd = kmalloc(sizeof(struct hifn_command), SLAB_ATOMIC);
++	if (cmd == NULL) {
++		hifnstats.hst_nomem++;
++		err = ENOMEM;
++		goto errout;
++	}
++	memset(cmd, 0, sizeof(*cmd));
++
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		cmd->src_skb = (struct sk_buff *)crp->crp_buf;
++		cmd->dst_skb = (struct sk_buff *)crp->crp_buf;
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		cmd->src_io = (struct uio *)crp->crp_buf;
++		cmd->dst_io = (struct uio *)crp->crp_buf;
++	} else {
++		cmd->src_buf = crp->crp_buf;
++		cmd->dst_buf = crp->crp_buf;
++	}
++
++	crd1 = crp->crp_desc;
++	if (crd1 == NULL) {
++		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++		err = EINVAL;
++		goto errout;
++	}
++	crd2 = crd1->crd_next;
++
++	if (crd2 == NULL) {
++		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
++		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
++		    crd1->crd_alg == CRYPTO_SHA1 ||
++		    crd1->crd_alg == CRYPTO_MD5) {
++			maccrd = crd1;
++			enccrd = NULL;
++		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
++		    crd1->crd_alg == CRYPTO_3DES_CBC ||
++		    crd1->crd_alg == CRYPTO_AES_CBC ||
++		    crd1->crd_alg == CRYPTO_ARC4) {
++			if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
++				cmd->base_masks |= HIFN_BASE_CMD_DECODE;
++			maccrd = NULL;
++			enccrd = crd1;
++		} else {
++			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++			err = EINVAL;
++			goto errout;
++		}
++	} else {
++		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
++                     crd1->crd_alg == CRYPTO_SHA1_HMAC ||
++                     crd1->crd_alg == CRYPTO_MD5 ||
++                     crd1->crd_alg == CRYPTO_SHA1) &&
++		    (crd2->crd_alg == CRYPTO_DES_CBC ||
++		     crd2->crd_alg == CRYPTO_3DES_CBC ||
++		     crd2->crd_alg == CRYPTO_AES_CBC ||
++		     crd2->crd_alg == CRYPTO_ARC4) &&
++		    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
++			cmd->base_masks = HIFN_BASE_CMD_DECODE;
++			maccrd = crd1;
++			enccrd = crd2;
++		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
++		     crd1->crd_alg == CRYPTO_ARC4 ||
++		     crd1->crd_alg == CRYPTO_3DES_CBC ||
++		     crd1->crd_alg == CRYPTO_AES_CBC) &&
++		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
++                     crd2->crd_alg == CRYPTO_SHA1_HMAC ||
++                     crd2->crd_alg == CRYPTO_MD5 ||
++                     crd2->crd_alg == CRYPTO_SHA1) &&
++		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
++			enccrd = crd1;
++			maccrd = crd2;
++		} else {
++			/*
++			 * We cannot order the 7751 as requested
++			 */
++			DPRINTF("%s,%d: %s %d,%d,%d - EINVAL\n",__FILE__,__LINE__,__FUNCTION__, crd1->crd_alg, crd2->crd_alg, crd1->crd_flags & CRD_F_ENCRYPT);
++			err = EINVAL;
++			goto errout;
++		}
++	}
++
++	if (enccrd) {
++		cmd->enccrd = enccrd;
++		cmd->base_masks |= HIFN_BASE_CMD_CRYPT;
++		switch (enccrd->crd_alg) {
++		case CRYPTO_ARC4:
++			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
++			break;
++		case CRYPTO_DES_CBC:
++			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
++			    HIFN_CRYPT_CMD_MODE_CBC |
++			    HIFN_CRYPT_CMD_NEW_IV;
++			break;
++		case CRYPTO_3DES_CBC:
++			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_3DES |
++			    HIFN_CRYPT_CMD_MODE_CBC |
++			    HIFN_CRYPT_CMD_NEW_IV;
++			break;
++		case CRYPTO_AES_CBC:
++			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES |
++			    HIFN_CRYPT_CMD_MODE_CBC |
++			    HIFN_CRYPT_CMD_NEW_IV;
++			break;
++		default:
++			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++			err = EINVAL;
++			goto errout;
++		}
++		if (enccrd->crd_alg != CRYPTO_ARC4) {
++			ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
++				HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
++			if (enccrd->crd_flags & CRD_F_ENCRYPT) {
++				if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
++					bcopy(enccrd->crd_iv, cmd->iv, ivlen);
++				else
++					bcopy(sc->sc_sessions[session].hs_iv,
++					    cmd->iv, ivlen);
++
++				if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
++				    == 0) {
++					crypto_copyback(crp->crp_flags,
++					    crp->crp_buf, enccrd->crd_inject,
++					    ivlen, cmd->iv);
++				}
++			} else {
++				if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
++					bcopy(enccrd->crd_iv, cmd->iv, ivlen);
++				else {
++					crypto_copydata(crp->crp_flags,
++					    crp->crp_buf, enccrd->crd_inject,
++					    ivlen, cmd->iv);
++				}
++			}
++		}
++
++		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
++			cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
++		cmd->ck = enccrd->crd_key;
++		cmd->cklen = enccrd->crd_klen >> 3;
++		cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
++
++		/* 
++		 * Need to specify the size for the AES key in the masks.
++		 */
++		if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) ==
++		    HIFN_CRYPT_CMD_ALG_AES) {
++			switch (cmd->cklen) {
++			case 16:
++				cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128;
++				break;
++			case 24:
++				cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192;
++				break;
++			case 32:
++				cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256;
++				break;
++			default:
++				DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
++				err = EINVAL;
++				goto errout;
++			}
++		}
++	}
++
++	if (maccrd) {
++		cmd->maccrd = maccrd;
++		cmd->base_masks |= HIFN_BASE_CMD_MAC;
++
++		switch (maccrd->crd_alg) {
++		case CRYPTO_MD5:
++			cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
++			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
++			    HIFN_MAC_CMD_POS_IPSEC;
++                       break;
++		case CRYPTO_MD5_HMAC:
++			cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
++			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
++			    HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
++			break;
++		case CRYPTO_SHA1:
++			cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
++			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
++			    HIFN_MAC_CMD_POS_IPSEC;
++			break;
++		case CRYPTO_SHA1_HMAC:
++			cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
++			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
++			    HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
++			break;
++		}
++
++		if (maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
++		     maccrd->crd_alg == CRYPTO_MD5_HMAC) {
++			cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
++			bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3);
++			bzero(cmd->mac + (maccrd->crd_klen >> 3),
++			    HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3));
++		}
++	}
++
++	cmd->crp = crp;
++	cmd->session_num = session;
++	cmd->softc = sc;
++
++	err = hifn_crypto(sc, cmd, crp, hint);
++	if (!err) {
++		return 0;
++	} else if (err == ERESTART) {
++		/*
++		 * There weren't enough resources to dispatch the request
++		 * to the part.  Notify the caller so they'll requeue this
++		 * request and resubmit it again soon.
++		 */
++#ifdef HIFN_DEBUG
++		if (hifn_debug)
++			device_printf(sc->sc_dev, "requeue request\n");
++#endif
++		kfree(cmd);
++		sc->sc_needwakeup |= CRYPTO_SYMQ;
++		return (err);
++	}
++
++errout:
++	if (cmd != NULL)
++		kfree(cmd);
++	if (err == EINVAL)
++		hifnstats.hst_invalid++;
++	else
++		hifnstats.hst_nomem++;
++	crp->crp_etype = err;
++	crypto_done(crp);
++	return (err);
++}
++
++static void
++hifn_abort(struct hifn_softc *sc)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	struct hifn_command *cmd;
++	struct cryptop *crp;
++	int i, u;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	i = dma->resk; u = dma->resu;
++	while (u != 0) {
++		cmd = dma->hifn_commands[i];
++		KASSERT(cmd != NULL, ("hifn_abort: null command slot %u", i));
++		dma->hifn_commands[i] = NULL;
++		crp = cmd->crp;
++
++		if ((dma->resr[i].l & htole32(HIFN_D_VALID)) == 0) {
++			/* Salvage what we can. */
++			u_int8_t *macbuf;
++
++			if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
++				macbuf = dma->result_bufs[i];
++				macbuf += 12;
++			} else
++				macbuf = NULL;
++			hifnstats.hst_opackets++;
++			hifn_callback(sc, cmd, macbuf);
++		} else {
++#if 0
++			if (cmd->src_map == cmd->dst_map) {
++				bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
++				    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
++			} else {
++				bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
++				    BUS_DMASYNC_POSTWRITE);
++				bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
++				    BUS_DMASYNC_POSTREAD);
++			}
++#endif
++
++			if (cmd->src_skb != cmd->dst_skb) {
++#ifdef NOTYET
++				m_freem(cmd->src_m);
++				crp->crp_buf = (caddr_t)cmd->dst_m;
++#else
++				device_printf(sc->sc_dev,
++						"%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
++						__FILE__, __LINE__);
++#endif
++			}
++
++			/* non-shared buffers cannot be restarted */
++			if (cmd->src_map != cmd->dst_map) {
++				/*
++				 * XXX should be EAGAIN, delayed until
++				 * after the reset.
++				 */
++				crp->crp_etype = ENOMEM;
++				pci_unmap_buf(sc, &cmd->dst);
++			} else
++				crp->crp_etype = ENOMEM;
++
++			pci_unmap_buf(sc, &cmd->src);
++
++			kfree(cmd);
++			if (crp->crp_etype != EAGAIN)
++				crypto_done(crp);
++		}
++
++		if (++i == HIFN_D_RES_RSIZE)
++			i = 0;
++		u--;
++	}
++	dma->resk = i; dma->resu = u;
++
++	hifn_reset_board(sc, 1);
++	hifn_init_dma(sc);
++	hifn_init_pci_registers(sc);
++}
++
++static void
++hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
++{
++	struct hifn_dma *dma = sc->sc_dma;
++	struct cryptop *crp = cmd->crp;
++	struct cryptodesc *crd;
++	int i, u, ivlen;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++#if 0
++	if (cmd->src_map == cmd->dst_map) {
++		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
++		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
++	} else {
++		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
++		    BUS_DMASYNC_POSTWRITE);
++		bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
++		    BUS_DMASYNC_POSTREAD);
++	}
++#endif
++
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		if (cmd->src_skb != cmd->dst_skb) {
++#ifdef NOTYET
++			crp->crp_buf = (caddr_t)cmd->dst_m;
++			totlen = cmd->src_mapsize;
++			for (m = cmd->dst_m; m != NULL; m = m->m_next) {
++				if (totlen < m->m_len) {
++					m->m_len = totlen;
++					totlen = 0;
++				} else
++					totlen -= m->m_len;
++			}
++			cmd->dst_m->m_pkthdr.len = cmd->src_m->m_pkthdr.len;
++			m_freem(cmd->src_m);
++#else
++			device_printf(sc->sc_dev,
++					"%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
++					__FILE__, __LINE__);
++#endif
++		}
++	}
++
++	if (cmd->sloplen != 0) {
++		crypto_copyback(crp->crp_flags, crp->crp_buf,
++		    cmd->src_mapsize - cmd->sloplen, cmd->sloplen,
++		    (caddr_t)&dma->slop[cmd->slopidx]);
++	}
++
++	i = dma->dstk; u = dma->dstu;
++	while (u != 0) {
++		if (i == HIFN_D_DST_RSIZE)
++			i = 0;
++#if 0
++		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
++		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
++#endif
++		if (dma->dstr[i].l & htole32(HIFN_D_VALID)) {
++#if 0
++			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
++			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
++#endif
++			break;
++		}
++		i++, u--;
++	}
++	dma->dstk = i; dma->dstu = u;
++
++	hifnstats.hst_obytes += cmd->dst_mapsize;
++
++	if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) ==
++	    HIFN_BASE_CMD_CRYPT) {
++		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
++			if (crd->crd_alg != CRYPTO_DES_CBC &&
++			    crd->crd_alg != CRYPTO_3DES_CBC &&
++			    crd->crd_alg != CRYPTO_AES_CBC)
++				continue;
++			ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
++				HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
++			crypto_copydata(crp->crp_flags, crp->crp_buf,
++			    crd->crd_skip + crd->crd_len - ivlen, ivlen,
++			    cmd->softc->sc_sessions[cmd->session_num].hs_iv);
++			break;
++		}
++	}
++
++	if (macbuf != NULL) {
++		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
++                        int len;
++
++			if (crd->crd_alg != CRYPTO_MD5 &&
++			    crd->crd_alg != CRYPTO_SHA1 &&
++			    crd->crd_alg != CRYPTO_MD5_HMAC &&
++			    crd->crd_alg != CRYPTO_SHA1_HMAC) {
++				continue;
++			}
++			len = cmd->softc->sc_sessions[cmd->session_num].hs_mlen;
++			crypto_copyback(crp->crp_flags, crp->crp_buf,
++			    crd->crd_inject, len, macbuf);
++			break;
++		}
++	}
++
++	if (cmd->src_map != cmd->dst_map)
++		pci_unmap_buf(sc, &cmd->dst);
++	pci_unmap_buf(sc, &cmd->src);
++	kfree(cmd);
++	crypto_done(crp);
++}
++
++/*
++ * 7811 PB3 rev/2 parts lock-up on burst writes to Group 0
++ * and Group 1 registers; avoid conditions that could create
++ * burst writes by doing a read in between the writes.
++ *
++ * NB: The read we interpose is always to the same register;
++ *     we do this because reading from an arbitrary (e.g. last)
++ *     register may not always work.
++ */
++static void
++hifn_write_reg_0(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
++{
++	if (sc->sc_flags & HIFN_IS_7811) {
++		if (sc->sc_bar0_lastreg == reg - 4)
++			readl(sc->sc_bar0 + HIFN_0_PUCNFG);
++		sc->sc_bar0_lastreg = reg;
++	}
++	writel(val, sc->sc_bar0 + reg);
++}
++
++static void
++hifn_write_reg_1(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
++{
++	if (sc->sc_flags & HIFN_IS_7811) {
++		if (sc->sc_bar1_lastreg == reg - 4)
++			readl(sc->sc_bar1 + HIFN_1_REVID);
++		sc->sc_bar1_lastreg = reg;
++	}
++	writel(val, sc->sc_bar1 + reg);
++}
++
++
++static struct pci_device_id hifn_pci_tbl[] = {
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7951,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7955,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7956,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ PCI_VENDOR_NETSEC, PCI_PRODUCT_NETSEC_7751,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ PCI_VENDOR_INVERTEX, PCI_PRODUCT_INVERTEX_AEON,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7811,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	/*
++	 * Other vendors share this PCI ID as well, such as
++	 * http://www.powercrypt.com, and obviously they also
++	 * use the same key.
++	 */
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7751,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++};
++MODULE_DEVICE_TABLE(pci, hifn_pci_tbl);
++
++static struct pci_driver hifn_driver = {
++	.name         = "hifn",
++	.id_table     = hifn_pci_tbl,
++	.probe        =	hifn_probe,
++	.remove       = hifn_remove,
++	/* add PM stuff here one day */
++};
++
++static int __init hifn_init (void)
++{
++	struct hifn_softc *sc = NULL;
++	int rc;
++
++	DPRINTF("%s(%p)\n", __FUNCTION__, hifn_init);
++
++	rc = pci_register_driver(&hifn_driver);
++	pci_register_driver_compat(&hifn_driver, rc);
++
++	return rc;
++}
++
++static void __exit hifn_exit (void)
++{
++	pci_unregister_driver(&hifn_driver);
++}
++
++module_init(hifn_init);
++module_exit(hifn_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("OCF driver for hifn PCI crypto devices");
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/hifn7751reg.h linux-2.6.23.16/crypto/ocf/hifn/hifn7751reg.h
+--- linux-2.6.23.16.old/crypto/ocf/hifn/hifn7751reg.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/hifn7751reg.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,540 @@
++/* $FreeBSD: src/sys/dev/hifn/hifn7751reg.h,v 1.7 2007/03/21 03:42:49 sam Exp $ */
++/*	$OpenBSD: hifn7751reg.h,v 1.35 2002/04/08 17:49:42 jason Exp $	*/
++
++/*-
++ * Invertex AEON / Hifn 7751 driver
++ * Copyright (c) 1999 Invertex Inc. All rights reserved.
++ * Copyright (c) 1999 Theo de Raadt
++ * Copyright (c) 2000-2001 Network Security Technologies, Inc.
++ *			http://www.netsec.net
++ *
++ * Please send any comments, feedback, bug-fixes, or feature requests to
++ * software@invertex.com.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
++ *
++ */
++#ifndef __HIFN_H__
++#define	__HIFN_H__
++
++/*
++ * Some PCI configuration space offset defines.  The names were made
++ * identical to the names used by the Linux kernel.
++ */
++#define	HIFN_BAR0		PCIR_BAR(0)	/* PUC register map */
++#define	HIFN_BAR1		PCIR_BAR(1)	/* DMA register map */
++#define	HIFN_TRDY_TIMEOUT	0x40
++#define	HIFN_RETRY_TIMEOUT	0x41
++
++/*
++ * PCI vendor and device identifiers
++ * (the names are preserved from their OpenBSD source).
++ */
++#define	PCI_VENDOR_HIFN		0x13a3		/* Hifn */
++#define	PCI_PRODUCT_HIFN_7751	0x0005		/* 7751 */
++#define	PCI_PRODUCT_HIFN_6500	0x0006		/* 6500 */
++#define	PCI_PRODUCT_HIFN_7811	0x0007		/* 7811 */
++#define	PCI_PRODUCT_HIFN_7855	0x001f		/* 7855 */
++#define	PCI_PRODUCT_HIFN_7951	0x0012		/* 7951 */
++#define	PCI_PRODUCT_HIFN_7955	0x0020		/* 7954/7955 */
++#define	PCI_PRODUCT_HIFN_7956	0x001d		/* 7956 */
++
++#define	PCI_VENDOR_INVERTEX	0x14e1		/* Invertex */
++#define	PCI_PRODUCT_INVERTEX_AEON 0x0005	/* AEON */
++
++#define	PCI_VENDOR_NETSEC	0x1660		/* NetSec */
++#define	PCI_PRODUCT_NETSEC_7751	0x7751		/* 7751 */
++
++/*
++ * The values below should multiple of 4 -- and be large enough to handle
++ * any command the driver implements.
++ *
++ * MAX_COMMAND = base command + mac command + encrypt command +
++ *			mac-key + rc4-key
++ * MAX_RESULT  = base result + mac result + mac + encrypt result
++ *			
++ *
++ */
++#define	HIFN_MAX_COMMAND	(8 + 8 + 8 + 64 + 260)
++#define	HIFN_MAX_RESULT		(8 + 4 + 20 + 4)
++
++/*
++ * hifn_desc_t
++ *
++ * Holds an individual descriptor for any of the rings.
++ */
++typedef struct hifn_desc {
++	volatile u_int32_t l;		/* length and status bits */
++	volatile u_int32_t p;
++} hifn_desc_t;
++
++/*
++ * Masks for the "length" field of struct hifn_desc.
++ */
++#define	HIFN_D_LENGTH		0x0000ffff	/* length bit mask */
++#define	HIFN_D_MASKDONEIRQ	0x02000000	/* mask the done interrupt */
++#define	HIFN_D_DESTOVER		0x04000000	/* destination overflow */
++#define	HIFN_D_OVER		0x08000000	/* overflow */
++#define	HIFN_D_LAST		0x20000000	/* last descriptor in chain */
++#define	HIFN_D_JUMP		0x40000000	/* jump descriptor */
++#define	HIFN_D_VALID		0x80000000	/* valid bit */
++
++
++/*
++ * Processing Unit Registers (offset from BASEREG0)
++ */
++#define	HIFN_0_PUDATA		0x00	/* Processing Unit Data */
++#define	HIFN_0_PUCTRL		0x04	/* Processing Unit Control */
++#define	HIFN_0_PUISR		0x08	/* Processing Unit Interrupt Status */
++#define	HIFN_0_PUCNFG		0x0c	/* Processing Unit Configuration */
++#define	HIFN_0_PUIER		0x10	/* Processing Unit Interrupt Enable */
++#define	HIFN_0_PUSTAT		0x14	/* Processing Unit Status/Chip ID */
++#define	HIFN_0_FIFOSTAT		0x18	/* FIFO Status */
++#define	HIFN_0_FIFOCNFG		0x1c	/* FIFO Configuration */
++#define	HIFN_0_PUCTRL2		0x28	/* Processing Unit Control (2nd map) */
++#define	HIFN_0_MUTE1		0x80
++#define	HIFN_0_MUTE2		0x90
++#define	HIFN_0_SPACESIZE	0x100	/* Register space size */
++
++/* Processing Unit Control Register (HIFN_0_PUCTRL) */
++#define	HIFN_PUCTRL_CLRSRCFIFO	0x0010	/* clear source fifo */
++#define	HIFN_PUCTRL_STOP	0x0008	/* stop pu */
++#define	HIFN_PUCTRL_LOCKRAM	0x0004	/* lock ram */
++#define	HIFN_PUCTRL_DMAENA	0x0002	/* enable dma */
++#define	HIFN_PUCTRL_RESET	0x0001	/* Reset processing unit */
++
++/* Processing Unit Interrupt Status Register (HIFN_0_PUISR) */
++#define	HIFN_PUISR_CMDINVAL	0x8000	/* Invalid command interrupt */
++#define	HIFN_PUISR_DATAERR	0x4000	/* Data error interrupt */
++#define	HIFN_PUISR_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
++#define	HIFN_PUISR_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
++#define	HIFN_PUISR_DSTOVER	0x0200	/* Destination overrun interrupt */
++#define	HIFN_PUISR_SRCCMD	0x0080	/* Source command interrupt */
++#define	HIFN_PUISR_SRCCTX	0x0040	/* Source context interrupt */
++#define	HIFN_PUISR_SRCDATA	0x0020	/* Source data interrupt */
++#define	HIFN_PUISR_DSTDATA	0x0010	/* Destination data interrupt */
++#define	HIFN_PUISR_DSTRESULT	0x0004	/* Destination result interrupt */
++
++/* Processing Unit Configuration Register (HIFN_0_PUCNFG) */
++#define	HIFN_PUCNFG_DRAMMASK	0xe000	/* DRAM size mask */
++#define	HIFN_PUCNFG_DSZ_256K	0x0000	/* 256k dram */
++#define	HIFN_PUCNFG_DSZ_512K	0x2000	/* 512k dram */
++#define	HIFN_PUCNFG_DSZ_1M	0x4000	/* 1m dram */
++#define	HIFN_PUCNFG_DSZ_2M	0x6000	/* 2m dram */
++#define	HIFN_PUCNFG_DSZ_4M	0x8000	/* 4m dram */
++#define	HIFN_PUCNFG_DSZ_8M	0xa000	/* 8m dram */
++#define	HIFN_PUNCFG_DSZ_16M	0xc000	/* 16m dram */
++#define	HIFN_PUCNFG_DSZ_32M	0xe000	/* 32m dram */
++#define	HIFN_PUCNFG_DRAMREFRESH	0x1800	/* DRAM refresh rate mask */
++#define	HIFN_PUCNFG_DRFR_512	0x0000	/* 512 divisor of ECLK */
++#define	HIFN_PUCNFG_DRFR_256	0x0800	/* 256 divisor of ECLK */
++#define	HIFN_PUCNFG_DRFR_128	0x1000	/* 128 divisor of ECLK */
++#define	HIFN_PUCNFG_TCALLPHASES	0x0200	/* your guess is as good as mine... */
++#define	HIFN_PUCNFG_TCDRVTOTEM	0x0100	/* your guess is as good as mine... */
++#define	HIFN_PUCNFG_BIGENDIAN	0x0080	/* DMA big endian mode */
++#define	HIFN_PUCNFG_BUS32	0x0040	/* Bus width 32bits */
++#define	HIFN_PUCNFG_BUS16	0x0000	/* Bus width 16 bits */
++#define	HIFN_PUCNFG_CHIPID	0x0020	/* Allow chipid from PUSTAT */
++#define	HIFN_PUCNFG_DRAM	0x0010	/* Context RAM is DRAM */
++#define	HIFN_PUCNFG_SRAM	0x0000	/* Context RAM is SRAM */
++#define	HIFN_PUCNFG_COMPSING	0x0004	/* Enable single compression context */
++#define	HIFN_PUCNFG_ENCCNFG	0x0002	/* Encryption configuration */
++
++/* Processing Unit Interrupt Enable Register (HIFN_0_PUIER) */
++#define	HIFN_PUIER_CMDINVAL	0x8000	/* Invalid command interrupt */
++#define	HIFN_PUIER_DATAERR	0x4000	/* Data error interrupt */
++#define	HIFN_PUIER_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
++#define	HIFN_PUIER_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
++#define	HIFN_PUIER_DSTOVER	0x0200	/* Destination overrun interrupt */
++#define	HIFN_PUIER_SRCCMD	0x0080	/* Source command interrupt */
++#define	HIFN_PUIER_SRCCTX	0x0040	/* Source context interrupt */
++#define	HIFN_PUIER_SRCDATA	0x0020	/* Source data interrupt */
++#define	HIFN_PUIER_DSTDATA	0x0010	/* Destination data interrupt */
++#define	HIFN_PUIER_DSTRESULT	0x0004	/* Destination result interrupt */
++
++/* Processing Unit Status Register/Chip ID (HIFN_0_PUSTAT) */
++#define	HIFN_PUSTAT_CMDINVAL	0x8000	/* Invalid command interrupt */
++#define	HIFN_PUSTAT_DATAERR	0x4000	/* Data error interrupt */
++#define	HIFN_PUSTAT_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
++#define	HIFN_PUSTAT_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
++#define	HIFN_PUSTAT_DSTOVER	0x0200	/* Destination overrun interrupt */
++#define	HIFN_PUSTAT_SRCCMD	0x0080	/* Source command interrupt */
++#define	HIFN_PUSTAT_SRCCTX	0x0040	/* Source context interrupt */
++#define	HIFN_PUSTAT_SRCDATA	0x0020	/* Source data interrupt */
++#define	HIFN_PUSTAT_DSTDATA	0x0010	/* Destination data interrupt */
++#define	HIFN_PUSTAT_DSTRESULT	0x0004	/* Destination result interrupt */
++#define	HIFN_PUSTAT_CHIPREV	0x00ff	/* Chip revision mask */
++#define	HIFN_PUSTAT_CHIPENA	0xff00	/* Chip enabled mask */
++#define	HIFN_PUSTAT_ENA_2	0x1100	/* Level 2 enabled */
++#define	HIFN_PUSTAT_ENA_1	0x1000	/* Level 1 enabled */
++#define	HIFN_PUSTAT_ENA_0	0x3000	/* Level 0 enabled */
++#define	HIFN_PUSTAT_REV_2	0x0020	/* 7751 PT6/2 */
++#define	HIFN_PUSTAT_REV_3	0x0030	/* 7751 PT6/3 */
++
++/* FIFO Status Register (HIFN_0_FIFOSTAT) */
++#define	HIFN_FIFOSTAT_SRC	0x7f00	/* Source FIFO available */
++#define	HIFN_FIFOSTAT_DST	0x007f	/* Destination FIFO available */
++
++/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
++#define	HIFN_FIFOCNFG_THRESHOLD	0x0400	/* must be written as this value */
++
++/*
++ * DMA Interface Registers (offset from BASEREG1)
++ */
++#define	HIFN_1_DMA_CRAR		0x0c	/* DMA Command Ring Address */
++#define	HIFN_1_DMA_SRAR		0x1c	/* DMA Source Ring Address */
++#define	HIFN_1_DMA_RRAR		0x2c	/* DMA Result Ring Address */
++#define	HIFN_1_DMA_DRAR		0x3c	/* DMA Destination Ring Address */
++#define	HIFN_1_DMA_CSR		0x40	/* DMA Status and Control */
++#define	HIFN_1_DMA_IER		0x44	/* DMA Interrupt Enable */
++#define	HIFN_1_DMA_CNFG		0x48	/* DMA Configuration */
++#define	HIFN_1_PLL		0x4c	/* 7955/7956: PLL config */
++#define	HIFN_1_7811_RNGENA	0x60	/* 7811: rng enable */
++#define	HIFN_1_7811_RNGCFG	0x64	/* 7811: rng config */
++#define	HIFN_1_7811_RNGDAT	0x68	/* 7811: rng data */
++#define	HIFN_1_7811_RNGSTS	0x6c	/* 7811: rng status */
++#define	HIFN_1_DMA_CNFG2	0x6c	/* 7955/7956: dma config #2 */
++#define	HIFN_1_7811_MIPSRST	0x94	/* 7811: MIPS reset */
++#define	HIFN_1_REVID		0x98	/* Revision ID */
++
++#define	HIFN_1_PUB_RESET	0x204	/* Public/RNG Reset */
++#define	HIFN_1_PUB_BASE		0x300	/* Public Base Address */
++#define	HIFN_1_PUB_OPLEN	0x304	/* 7951-compat Public Operand Length */
++#define	HIFN_1_PUB_OP		0x308	/* 7951-compat Public Operand */
++#define	HIFN_1_PUB_STATUS	0x30c	/* 7951-compat Public Status */
++#define	HIFN_1_PUB_IEN		0x310	/* Public Interrupt enable */
++#define	HIFN_1_RNG_CONFIG	0x314	/* RNG config */
++#define	HIFN_1_RNG_DATA		0x318	/* RNG data */
++#define	HIFN_1_PUB_MODE		0x320	/* PK mode */
++#define	HIFN_1_PUB_FIFO_OPLEN	0x380	/* first element of oplen fifo */
++#define	HIFN_1_PUB_FIFO_OP	0x384	/* first element of op fifo */
++#define	HIFN_1_PUB_MEM		0x400	/* start of Public key memory */
++#define	HIFN_1_PUB_MEMEND	0xbff	/* end of Public key memory */
++
++/* DMA Status and Control Register (HIFN_1_DMA_CSR) */
++#define	HIFN_DMACSR_D_CTRLMASK	0xc0000000	/* Destinition Ring Control */
++#define	HIFN_DMACSR_D_CTRL_NOP	0x00000000	/* Dest. Control: no-op */
++#define	HIFN_DMACSR_D_CTRL_DIS	0x40000000	/* Dest. Control: disable */
++#define	HIFN_DMACSR_D_CTRL_ENA	0x80000000	/* Dest. Control: enable */
++#define	HIFN_DMACSR_D_ABORT	0x20000000	/* Destinition Ring PCIAbort */
++#define	HIFN_DMACSR_D_DONE	0x10000000	/* Destinition Ring Done */
++#define	HIFN_DMACSR_D_LAST	0x08000000	/* Destinition Ring Last */
++#define	HIFN_DMACSR_D_WAIT	0x04000000	/* Destinition Ring Waiting */
++#define	HIFN_DMACSR_D_OVER	0x02000000	/* Destinition Ring Overflow */
++#define	HIFN_DMACSR_R_CTRL	0x00c00000	/* Result Ring Control */
++#define	HIFN_DMACSR_R_CTRL_NOP	0x00000000	/* Result Control: no-op */
++#define	HIFN_DMACSR_R_CTRL_DIS	0x00400000	/* Result Control: disable */
++#define	HIFN_DMACSR_R_CTRL_ENA	0x00800000	/* Result Control: enable */
++#define	HIFN_DMACSR_R_ABORT	0x00200000	/* Result Ring PCI Abort */
++#define	HIFN_DMACSR_R_DONE	0x00100000	/* Result Ring Done */
++#define	HIFN_DMACSR_R_LAST	0x00080000	/* Result Ring Last */
++#define	HIFN_DMACSR_R_WAIT	0x00040000	/* Result Ring Waiting */
++#define	HIFN_DMACSR_R_OVER	0x00020000	/* Result Ring Overflow */
++#define	HIFN_DMACSR_S_CTRL	0x0000c000	/* Source Ring Control */
++#define	HIFN_DMACSR_S_CTRL_NOP	0x00000000	/* Source Control: no-op */
++#define	HIFN_DMACSR_S_CTRL_DIS	0x00004000	/* Source Control: disable */
++#define	HIFN_DMACSR_S_CTRL_ENA	0x00008000	/* Source Control: enable */
++#define	HIFN_DMACSR_S_ABORT	0x00002000	/* Source Ring PCI Abort */
++#define	HIFN_DMACSR_S_DONE	0x00001000	/* Source Ring Done */
++#define	HIFN_DMACSR_S_LAST	0x00000800	/* Source Ring Last */
++#define	HIFN_DMACSR_S_WAIT	0x00000400	/* Source Ring Waiting */
++#define	HIFN_DMACSR_ILLW	0x00000200	/* Illegal write (7811 only) */
++#define	HIFN_DMACSR_ILLR	0x00000100	/* Illegal read (7811 only) */
++#define	HIFN_DMACSR_C_CTRL	0x000000c0	/* Command Ring Control */
++#define	HIFN_DMACSR_C_CTRL_NOP	0x00000000	/* Command Control: no-op */
++#define	HIFN_DMACSR_C_CTRL_DIS	0x00000040	/* Command Control: disable */
++#define	HIFN_DMACSR_C_CTRL_ENA	0x00000080	/* Command Control: enable */
++#define	HIFN_DMACSR_C_ABORT	0x00000020	/* Command Ring PCI Abort */
++#define	HIFN_DMACSR_C_DONE	0x00000010	/* Command Ring Done */
++#define	HIFN_DMACSR_C_LAST	0x00000008	/* Command Ring Last */
++#define	HIFN_DMACSR_C_WAIT	0x00000004	/* Command Ring Waiting */
++#define	HIFN_DMACSR_PUBDONE	0x00000002	/* Public op done (7951 only) */
++#define	HIFN_DMACSR_ENGINE	0x00000001	/* Command Ring Engine IRQ */
++
++/* DMA Interrupt Enable Register (HIFN_1_DMA_IER) */
++#define	HIFN_DMAIER_D_ABORT	0x20000000	/* Destination Ring PCIAbort */
++#define	HIFN_DMAIER_D_DONE	0x10000000	/* Destination Ring Done */
++#define	HIFN_DMAIER_D_LAST	0x08000000	/* Destination Ring Last */
++#define	HIFN_DMAIER_D_WAIT	0x04000000	/* Destination Ring Waiting */
++#define	HIFN_DMAIER_D_OVER	0x02000000	/* Destination Ring Overflow */
++#define	HIFN_DMAIER_R_ABORT	0x00200000	/* Result Ring PCI Abort */
++#define	HIFN_DMAIER_R_DONE	0x00100000	/* Result Ring Done */
++#define	HIFN_DMAIER_R_LAST	0x00080000	/* Result Ring Last */
++#define	HIFN_DMAIER_R_WAIT	0x00040000	/* Result Ring Waiting */
++#define	HIFN_DMAIER_R_OVER	0x00020000	/* Result Ring Overflow */
++#define	HIFN_DMAIER_S_ABORT	0x00002000	/* Source Ring PCI Abort */
++#define	HIFN_DMAIER_S_DONE	0x00001000	/* Source Ring Done */
++#define	HIFN_DMAIER_S_LAST	0x00000800	/* Source Ring Last */
++#define	HIFN_DMAIER_S_WAIT	0x00000400	/* Source Ring Waiting */
++#define	HIFN_DMAIER_ILLW	0x00000200	/* Illegal write (7811 only) */
++#define	HIFN_DMAIER_ILLR	0x00000100	/* Illegal read (7811 only) */
++#define	HIFN_DMAIER_C_ABORT	0x00000020	/* Command Ring PCI Abort */
++#define	HIFN_DMAIER_C_DONE	0x00000010	/* Command Ring Done */
++#define	HIFN_DMAIER_C_LAST	0x00000008	/* Command Ring Last */
++#define	HIFN_DMAIER_C_WAIT	0x00000004	/* Command Ring Waiting */
++#define	HIFN_DMAIER_PUBDONE	0x00000002	/* public op done (7951 only) */
++#define	HIFN_DMAIER_ENGINE	0x00000001	/* Engine IRQ */
++
++/* DMA Configuration Register (HIFN_1_DMA_CNFG) */
++#define	HIFN_DMACNFG_BIGENDIAN	0x10000000	/* big endian mode */
++#define	HIFN_DMACNFG_POLLFREQ	0x00ff0000	/* Poll frequency mask */
++#define	HIFN_DMACNFG_UNLOCK	0x00000800
++#define	HIFN_DMACNFG_POLLINVAL	0x00000700	/* Invalid Poll Scalar */
++#define	HIFN_DMACNFG_LAST	0x00000010	/* Host control LAST bit */
++#define	HIFN_DMACNFG_MODE	0x00000004	/* DMA mode */
++#define	HIFN_DMACNFG_DMARESET	0x00000002	/* DMA Reset # */
++#define	HIFN_DMACNFG_MSTRESET	0x00000001	/* Master Reset # */
++
++/* DMA Configuration Register (HIFN_1_DMA_CNFG2) */
++#define	HIFN_DMACNFG2_PKSWAP32	(1 << 19)	/* swap the OPLEN/OP reg */
++#define	HIFN_DMACNFG2_PKSWAP8	(1 << 18)	/* swap the bits of OPLEN/OP */
++#define	HIFN_DMACNFG2_BAR0_SWAP32 (1<<17)	/* swap the bytes of BAR0 */
++#define	HIFN_DMACNFG2_BAR1_SWAP8 (1<<16)	/* swap the bits  of BAR0 */
++#define	HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT 12
++#define	HIFN_DMACNFG2_INIT_READ_BURST_SHIFT 8
++#define	HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT 4
++#define	HIFN_DMACNFG2_TGT_READ_BURST_SHIFT  0
++
++/* 7811 RNG Enable Register (HIFN_1_7811_RNGENA) */
++#define	HIFN_7811_RNGENA_ENA	0x00000001	/* enable RNG */
++
++/* 7811 RNG Config Register (HIFN_1_7811_RNGCFG) */
++#define	HIFN_7811_RNGCFG_PRE1	0x00000f00	/* first prescalar */
++#define	HIFN_7811_RNGCFG_OPRE	0x00000080	/* output prescalar */
++#define	HIFN_7811_RNGCFG_DEFL	0x00000f80	/* 2 words/ 1/100 sec */
++
++/* 7811 RNG Status Register (HIFN_1_7811_RNGSTS) */
++#define	HIFN_7811_RNGSTS_RDY	0x00004000	/* two numbers in FIFO */
++#define	HIFN_7811_RNGSTS_UFL	0x00001000	/* rng underflow */
++
++/* 7811 MIPS Reset Register (HIFN_1_7811_MIPSRST) */
++#define	HIFN_MIPSRST_BAR2SIZE	0xffff0000	/* sdram size */
++#define	HIFN_MIPSRST_GPRAMINIT	0x00008000	/* gpram can be accessed */
++#define	HIFN_MIPSRST_CRAMINIT	0x00004000	/* ctxram can be accessed */
++#define	HIFN_MIPSRST_LED2	0x00000400	/* external LED2 */
++#define	HIFN_MIPSRST_LED1	0x00000200	/* external LED1 */
++#define	HIFN_MIPSRST_LED0	0x00000100	/* external LED0 */
++#define	HIFN_MIPSRST_MIPSDIS	0x00000004	/* disable MIPS */
++#define	HIFN_MIPSRST_MIPSRST	0x00000002	/* warm reset MIPS */
++#define	HIFN_MIPSRST_MIPSCOLD	0x00000001	/* cold reset MIPS */
++
++/* Public key reset register (HIFN_1_PUB_RESET) */
++#define	HIFN_PUBRST_RESET	0x00000001	/* reset public/rng unit */
++
++/* Public operation register (HIFN_1_PUB_OP) */
++#define	HIFN_PUBOP_AOFFSET	0x0000003e	/* A offset */
++#define	HIFN_PUBOP_BOFFSET	0x00000fc0	/* B offset */
++#define	HIFN_PUBOP_MOFFSET	0x0003f000	/* M offset */
++#define	HIFN_PUBOP_OP_MASK	0x003c0000	/* Opcode: */
++#define	HIFN_PUBOP_OP_NOP	0x00000000	/*  NOP */
++#define	HIFN_PUBOP_OP_ADD	0x00040000	/*  ADD */
++#define	HIFN_PUBOP_OP_ADDC	0x00080000	/*  ADD w/carry */
++#define	HIFN_PUBOP_OP_SUB	0x000c0000	/*  SUB */
++#define	HIFN_PUBOP_OP_SUBC	0x00100000	/*  SUB w/carry */
++#define	HIFN_PUBOP_OP_MODADD	0x00140000	/*  Modular ADD */
++#define	HIFN_PUBOP_OP_MODSUB	0x00180000	/*  Modular SUB */
++#define	HIFN_PUBOP_OP_INCA	0x001c0000	/*  INC A */
++#define	HIFN_PUBOP_OP_DECA	0x00200000	/*  DEC A */
++#define	HIFN_PUBOP_OP_MULT	0x00240000	/*  MULT */
++#define	HIFN_PUBOP_OP_MODMULT	0x00280000	/*  Modular MULT */
++#define	HIFN_PUBOP_OP_MODRED	0x002c0000	/*  Modular Red */
++#define	HIFN_PUBOP_OP_MODEXP	0x00300000	/*  Modular Exp */
++
++/* Public operand length register (HIFN_1_PUB_OPLEN) */
++#define	HIFN_PUBOPLEN_MODLEN	0x0000007f
++#define	HIFN_PUBOPLEN_EXPLEN	0x0003ff80
++#define	HIFN_PUBOPLEN_REDLEN	0x003c0000
++
++/* Public status register (HIFN_1_PUB_STATUS) */
++#define	HIFN_PUBSTS_DONE	0x00000001	/* operation done */
++#define	HIFN_PUBSTS_CARRY	0x00000002	/* carry */
++#define	HIFN_PUBSTS_FIFO_EMPTY	0x00000100	/* fifo empty */
++#define	HIFN_PUBSTS_FIFO_FULL	0x00000200	/* fifo full */
++#define	HIFN_PUBSTS_FIFO_OVFL	0x00000400	/* fifo overflow */
++#define	HIFN_PUBSTS_FIFO_WRITE	0x000f0000	/* fifo write */
++#define	HIFN_PUBSTS_FIFO_READ	0x0f000000	/* fifo read */
++
++/* Public interrupt enable register (HIFN_1_PUB_IEN) */
++#define	HIFN_PUBIEN_DONE	0x00000001	/* operation done interrupt */
++
++/* Random number generator config register (HIFN_1_RNG_CONFIG) */
++#define	HIFN_RNGCFG_ENA		0x00000001	/* enable rng */
++
++/*
++ * Register offsets in register set 1
++ */
++
++#define	HIFN_UNLOCK_SECRET1	0xf4
++#define	HIFN_UNLOCK_SECRET2	0xfc
++
++/*
++ * PLL config register
++ *
++ * This register is present only on 7954/7955/7956 parts. It must be
++ * programmed according to the bus interface method used by the h/w.
++ * Note that the parts require a stable clock.  Since the PCI clock
++ * may vary the reference clock must usually be used.  To avoid
++ * overclocking the core logic, setup must be done carefully, refer
++ * to the driver for details.  The exact multiplier required varies
++ * by part and system configuration; refer to the Hifn documentation.
++ */
++#define	HIFN_PLL_REF_SEL	0x00000001	/* REF/HBI clk selection */
++#define	HIFN_PLL_BP		0x00000002	/* bypass (used during setup) */
++/* bit 2 reserved */
++#define	HIFN_PLL_PK_CLK_SEL	0x00000008	/* public key clk select */
++#define	HIFN_PLL_PE_CLK_SEL	0x00000010	/* packet engine clk select */
++/* bits 5-9 reserved */
++#define	HIFN_PLL_MBSET		0x00000400	/* must be set to 1 */
++#define	HIFN_PLL_ND		0x00003800	/* Fpll_ref multiplier select */
++#define	HIFN_PLL_ND_SHIFT	11
++#define	HIFN_PLL_ND_2		0x00000000	/* 2x */
++#define	HIFN_PLL_ND_4		0x00000800	/* 4x */
++#define	HIFN_PLL_ND_6		0x00001000	/* 6x */
++#define	HIFN_PLL_ND_8		0x00001800	/* 8x */
++#define	HIFN_PLL_ND_10		0x00002000	/* 10x */
++#define	HIFN_PLL_ND_12		0x00002800	/* 12x */
++/* bits 14-15 reserved */
++#define	HIFN_PLL_IS		0x00010000	/* charge pump current select */
++/* bits 17-31 reserved */
++
++/*
++ * Board configuration specifies only these bits.
++ */
++#define	HIFN_PLL_CONFIG		(HIFN_PLL_IS|HIFN_PLL_ND|HIFN_PLL_REF_SEL)
++
++/*
++ * Public Key Engine Mode Register
++ */
++#define	HIFN_PKMODE_HOSTINVERT	(1 << 0)	/* HOST INVERT */
++#define	HIFN_PKMODE_ENHANCED	(1 << 1)	/* Enable enhanced mode */
++
++
++/*********************************************************************
++ * Structs for board commands 
++ *
++ *********************************************************************/
++
++/*
++ * Structure to help build up the command data structure.
++ */
++typedef struct hifn_base_command {
++	volatile u_int16_t masks;
++	volatile u_int16_t session_num;
++	volatile u_int16_t total_source_count;
++	volatile u_int16_t total_dest_count;
++} hifn_base_command_t;
++
++#define	HIFN_BASE_CMD_MAC		0x0400
++#define	HIFN_BASE_CMD_CRYPT		0x0800
++#define	HIFN_BASE_CMD_DECODE		0x2000
++#define	HIFN_BASE_CMD_SRCLEN_M		0xc000
++#define	HIFN_BASE_CMD_SRCLEN_S		14
++#define	HIFN_BASE_CMD_DSTLEN_M		0x3000
++#define	HIFN_BASE_CMD_DSTLEN_S		12
++#define	HIFN_BASE_CMD_LENMASK_HI	0x30000
++#define	HIFN_BASE_CMD_LENMASK_LO	0x0ffff
++
++/*
++ * Structure to help build up the command data structure.
++ */
++typedef struct hifn_crypt_command {
++	volatile u_int16_t masks;
++	volatile u_int16_t header_skip;
++	volatile u_int16_t source_count;
++	volatile u_int16_t reserved;
++} hifn_crypt_command_t;
++
++#define	HIFN_CRYPT_CMD_ALG_MASK		0x0003		/* algorithm: */
++#define	HIFN_CRYPT_CMD_ALG_DES		0x0000		/*   DES */
++#define	HIFN_CRYPT_CMD_ALG_3DES		0x0001		/*   3DES */
++#define	HIFN_CRYPT_CMD_ALG_RC4		0x0002		/*   RC4 */
++#define	HIFN_CRYPT_CMD_ALG_AES		0x0003		/*   AES */
++#define	HIFN_CRYPT_CMD_MODE_MASK	0x0018		/* Encrypt mode: */
++#define	HIFN_CRYPT_CMD_MODE_ECB		0x0000		/*   ECB */
++#define	HIFN_CRYPT_CMD_MODE_CBC		0x0008		/*   CBC */
++#define	HIFN_CRYPT_CMD_MODE_CFB		0x0010		/*   CFB */
++#define	HIFN_CRYPT_CMD_MODE_OFB		0x0018		/*   OFB */
++#define	HIFN_CRYPT_CMD_CLR_CTX		0x0040		/* clear context */
++#define	HIFN_CRYPT_CMD_NEW_KEY		0x0800		/* expect new key */
++#define	HIFN_CRYPT_CMD_NEW_IV		0x1000		/* expect new iv */
++
++#define	HIFN_CRYPT_CMD_SRCLEN_M		0xc000
++#define	HIFN_CRYPT_CMD_SRCLEN_S		14
++
++#define	HIFN_CRYPT_CMD_KSZ_MASK		0x0600		/* AES key size: */
++#define	HIFN_CRYPT_CMD_KSZ_128		0x0000		/*   128 bit */
++#define	HIFN_CRYPT_CMD_KSZ_192		0x0200		/*   192 bit */
++#define	HIFN_CRYPT_CMD_KSZ_256		0x0400		/*   256 bit */
++
++/*
++ * Structure to help build up the command data structure.
++ */
++typedef struct hifn_mac_command {
++	volatile u_int16_t masks;
++	volatile u_int16_t header_skip;
++	volatile u_int16_t source_count;
++	volatile u_int16_t reserved;
++} hifn_mac_command_t;
++
++#define	HIFN_MAC_CMD_ALG_MASK		0x0001
++#define	HIFN_MAC_CMD_ALG_SHA1		0x0000
++#define	HIFN_MAC_CMD_ALG_MD5		0x0001
++#define	HIFN_MAC_CMD_MODE_MASK		0x000c
++#define	HIFN_MAC_CMD_MODE_HMAC		0x0000
++#define	HIFN_MAC_CMD_MODE_SSL_MAC	0x0004
++#define	HIFN_MAC_CMD_MODE_HASH		0x0008
++#define	HIFN_MAC_CMD_MODE_FULL		0x0004
++#define	HIFN_MAC_CMD_TRUNC		0x0010
++#define	HIFN_MAC_CMD_RESULT		0x0020
++#define	HIFN_MAC_CMD_APPEND		0x0040
++#define	HIFN_MAC_CMD_SRCLEN_M		0xc000
++#define	HIFN_MAC_CMD_SRCLEN_S		14
++
++/*
++ * MAC POS IPsec initiates authentication after encryption on encodes
++ * and before decryption on decodes.
++ */
++#define	HIFN_MAC_CMD_POS_IPSEC		0x0200
++#define	HIFN_MAC_CMD_NEW_KEY		0x0800
++
++/*
++ * The poll frequency and poll scalar defines are unshifted values used
++ * to set fields in the DMA Configuration Register.
++ */
++#ifndef HIFN_POLL_FREQUENCY
++#define	HIFN_POLL_FREQUENCY	0x1
++#endif
++
++#ifndef HIFN_POLL_SCALAR
++#define	HIFN_POLL_SCALAR	0x0
++#endif
++
++#define	HIFN_MAX_SEGLEN 	0xffff		/* maximum dma segment len */
++#define	HIFN_MAX_DMALEN		0x3ffff		/* maximum dma length */
++#endif /* __HIFN_H__ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/hifn7751var.h linux-2.6.23.16/crypto/ocf/hifn/hifn7751var.h
+--- linux-2.6.23.16.old/crypto/ocf/hifn/hifn7751var.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/hifn7751var.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,369 @@
++/* $FreeBSD: src/sys/dev/hifn/hifn7751var.h,v 1.9 2007/03/21 03:42:49 sam Exp $ */
++/*	$OpenBSD: hifn7751var.h,v 1.42 2002/04/08 17:49:42 jason Exp $	*/
++
++/*-
++ * Invertex AEON / Hifn 7751 driver
++ * Copyright (c) 1999 Invertex Inc. All rights reserved.
++ * Copyright (c) 1999 Theo de Raadt
++ * Copyright (c) 2000-2001 Network Security Technologies, Inc.
++ *			http://www.netsec.net
++ *
++ * Please send any comments, feedback, bug-fixes, or feature requests to
++ * software@invertex.com.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
++ *
++ */
++
++#ifndef __HIFN7751VAR_H__
++#define __HIFN7751VAR_H__
++
++#ifdef __KERNEL__
++
++/*
++ * Some configurable values for the driver.  By default command+result
++ * descriptor rings are the same size.  The src+dst descriptor rings
++ * are sized at 3.5x the number of potential commands.  Slower parts
++ * (e.g. 7951) tend to run out of src descriptors; faster parts (7811)
++ * src+cmd/result descriptors.  It's not clear that increasing the size
++ * of the descriptor rings helps performance significantly as other
++ * factors tend to come into play (e.g. copying misaligned packets).
++ */
++#define	HIFN_D_CMD_RSIZE	24	/* command descriptors */
++#define	HIFN_D_SRC_RSIZE	((HIFN_D_CMD_RSIZE * 7) / 2)	/* source descriptors */
++#define	HIFN_D_RES_RSIZE	HIFN_D_CMD_RSIZE	/* result descriptors */
++#define	HIFN_D_DST_RSIZE	HIFN_D_SRC_RSIZE	/* destination descriptors */
++
++/*
++ *  Length values for cryptography
++ */
++#define HIFN_DES_KEY_LENGTH		8
++#define HIFN_3DES_KEY_LENGTH		24
++#define HIFN_MAX_CRYPT_KEY_LENGTH	HIFN_3DES_KEY_LENGTH
++#define HIFN_IV_LENGTH			8
++#define	HIFN_AES_IV_LENGTH		16
++#define HIFN_MAX_IV_LENGTH		HIFN_AES_IV_LENGTH
++
++/*
++ *  Length values for authentication
++ */
++#define HIFN_MAC_KEY_LENGTH		64
++#define HIFN_MD5_LENGTH			16
++#define HIFN_SHA1_LENGTH		20
++#define HIFN_MAC_TRUNC_LENGTH		12
++
++#define MAX_SCATTER 64
++
++/*
++ * Data structure to hold all 4 rings and any other ring related data.
++ */
++struct hifn_dma {
++	/*
++	 *  Descriptor rings.  We add +1 to the size to accomidate the
++	 *  jump descriptor.
++	 */
++	struct hifn_desc	cmdr[HIFN_D_CMD_RSIZE+1];
++	struct hifn_desc	srcr[HIFN_D_SRC_RSIZE+1];
++	struct hifn_desc	dstr[HIFN_D_DST_RSIZE+1];
++	struct hifn_desc	resr[HIFN_D_RES_RSIZE+1];
++
++	struct hifn_command	*hifn_commands[HIFN_D_RES_RSIZE];
++
++	u_char			command_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_COMMAND];
++	u_char			result_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_RESULT];
++	u_int32_t		slop[HIFN_D_CMD_RSIZE];
++
++	u_int64_t		test_src, test_dst;
++
++	/*
++	 *  Our current positions for insertion and removal from the desriptor
++	 *  rings. 
++	 */
++	int			cmdi, srci, dsti, resi;
++	volatile int		cmdu, srcu, dstu, resu;
++	int			cmdk, srck, dstk, resk;
++};
++
++struct hifn_session {
++	int hs_used;
++	int hs_mlen;
++	u_int8_t hs_iv[HIFN_MAX_IV_LENGTH];
++};
++
++#define	HIFN_RING_SYNC(sc, r, i, f)					\
++	/* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
++
++#define	HIFN_CMDR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), cmdr, (i), (f))
++#define	HIFN_RESR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), resr, (i), (f))
++#define	HIFN_SRCR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), srcr, (i), (f))
++#define	HIFN_DSTR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), dstr, (i), (f))
++
++#define	HIFN_CMD_SYNC(sc, i, f)						\
++	/* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
++
++#define	HIFN_RES_SYNC(sc, i, f)						\
++	/* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
++
++typedef int bus_size_t;
++
++/*
++ * Holds data specific to a single HIFN board.
++ */
++struct hifn_softc {
++	softc_device_decl		 sc_dev;
++
++	struct pci_dev		*sc_pcidev;	/* PCI device pointer */
++	spinlock_t		sc_mtx;		/* per-instance lock */
++
++	int			sc_num;		/* for multiple devs */
++
++	ocf_iomem_t		sc_bar0;
++	bus_size_t		sc_bar0_lastreg;/* bar0 last reg written */
++	ocf_iomem_t		sc_bar1;
++	bus_size_t		sc_bar1_lastreg;/* bar1 last reg written */
++
++	int			sc_irq;
++
++	u_int32_t		sc_dmaier;
++	u_int32_t		sc_drammodel;	/* 1=dram, 0=sram */
++	u_int32_t		sc_pllconfig;	/* 7954/7955/7956 PLL config */
++
++	struct hifn_dma		*sc_dma;
++	dma_addr_t		sc_dma_physaddr;/* physical address of sc_dma */
++
++	int			sc_dmansegs;
++	int32_t			sc_cid;
++	int			sc_maxses;
++	int			sc_nsessions;
++	struct hifn_session	*sc_sessions;
++	int			sc_ramsize;
++	int			sc_flags;
++#define	HIFN_HAS_RNG		0x1	/* includes random number generator */
++#define	HIFN_HAS_PUBLIC		0x2	/* includes public key support */
++#define	HIFN_HAS_AES		0x4	/* includes AES support */
++#define	HIFN_IS_7811		0x8	/* Hifn 7811 part */
++#define	HIFN_IS_7956		0x10	/* Hifn 7956/7955 don't have SDRAM */
++
++	struct timer_list	sc_tickto;	/* for managing DMA */
++
++	int			sc_rngfirst;
++	int			sc_rnghz;	/* RNG polling frequency */
++
++	int			sc_c_busy;	/* command ring busy */
++	int			sc_s_busy;	/* source data ring busy */
++	int			sc_d_busy;	/* destination data ring busy */
++	int			sc_r_busy;	/* result ring busy */
++	int			sc_active;	/* for initial countdown */
++	int			sc_needwakeup;	/* ops q'd wating on resources */
++	int			sc_curbatch;	/* # ops submitted w/o int */
++	int			sc_suspended;
++#ifdef HIFN_VULCANDEV
++	struct cdev            *sc_pkdev;
++#endif
++};
++
++#define	HIFN_LOCK(_sc)		spin_lock_irqsave(&(_sc)->sc_mtx, l_flags)
++#define	HIFN_UNLOCK(_sc)	spin_unlock_irqrestore(&(_sc)->sc_mtx, l_flags)
++
++/*
++ *  hifn_command_t
++ *
++ *  This is the control structure used to pass commands to hifn_encrypt().
++ *
++ *  flags
++ *  -----
++ *  Flags is the bitwise "or" values for command configuration.  A single
++ *  encrypt direction needs to be set:
++ *
++ *	HIFN_ENCODE or HIFN_DECODE
++ *
++ *  To use cryptography, a single crypto algorithm must be included:
++ *
++ *	HIFN_CRYPT_3DES or HIFN_CRYPT_DES
++ *
++ *  To use authentication is used, a single MAC algorithm must be included:
++ *
++ *	HIFN_MAC_MD5 or HIFN_MAC_SHA1
++ *
++ *  By default MD5 uses a 16 byte hash and SHA-1 uses a 20 byte hash.
++ *  If the value below is set, hash values are truncated or assumed
++ *  truncated to 12 bytes:
++ *
++ *	HIFN_MAC_TRUNC
++ *
++ *  Keys for encryption and authentication can be sent as part of a command,
++ *  or the last key value used with a particular session can be retrieved
++ *  and used again if either of these flags are not specified.
++ *
++ *	HIFN_CRYPT_NEW_KEY, HIFN_MAC_NEW_KEY
++ *
++ *  session_num
++ *  -----------
++ *  A number between 0 and 2048 (for DRAM models) or a number between 
++ *  0 and 768 (for SRAM models).  Those who don't want to use session
++ *  numbers should leave value at zero and send a new crypt key and/or
++ *  new MAC key on every command.  If you use session numbers and
++ *  don't send a key with a command, the last key sent for that same
++ *  session number will be used.
++ *
++ *  Warning:  Using session numbers and multiboard at the same time
++ *            is currently broken.
++ *
++ *  mbuf
++ *  ----
++ *  Either fill in the mbuf pointer and npa=0 or
++ *	 fill packp[] and packl[] and set npa to > 0
++ * 
++ *  mac_header_skip
++ *  ---------------
++ *  The number of bytes of the source_buf that are skipped over before
++ *  authentication begins.  This must be a number between 0 and 2^16-1
++ *  and can be used by IPsec implementers to skip over IP headers.
++ *  *** Value ignored if authentication not used ***
++ *
++ *  crypt_header_skip
++ *  -----------------
++ *  The number of bytes of the source_buf that are skipped over before
++ *  the cryptographic operation begins.  This must be a number between 0
++ *  and 2^16-1.  For IPsec, this number will always be 8 bytes larger
++ *  than the auth_header_skip (to skip over the ESP header).
++ *  *** Value ignored if cryptography not used ***
++ *
++ */
++struct hifn_operand {
++	union {
++		struct sk_buff *skb;
++		struct uio *io;
++		unsigned char *buf;
++	} u;
++	void		*map;
++	bus_size_t	mapsize;
++	int		nsegs;
++	struct {
++	    dma_addr_t  ds_addr;
++	    int         ds_len;
++	} segs[MAX_SCATTER];
++};
++
++struct hifn_command {
++	u_int16_t session_num;
++	u_int16_t base_masks, cry_masks, mac_masks;
++	u_int8_t iv[HIFN_MAX_IV_LENGTH], *ck, mac[HIFN_MAC_KEY_LENGTH];
++	int cklen;
++	int sloplen, slopidx;
++
++	struct hifn_operand src;
++	struct hifn_operand dst;
++
++	struct hifn_softc *softc;
++	struct cryptop *crp;
++	struct cryptodesc *enccrd, *maccrd;
++};
++
++#define	src_skb		src.u.skb
++#define	src_io		src.u.io
++#define	src_map		src.map
++#define	src_mapsize	src.mapsize
++#define	src_segs	src.segs
++#define	src_nsegs	src.nsegs
++#define	src_buf		src.u.buf
++
++#define	dst_skb		dst.u.skb
++#define	dst_io		dst.u.io
++#define	dst_map		dst.map
++#define	dst_mapsize	dst.mapsize
++#define	dst_segs	dst.segs
++#define	dst_nsegs	dst.nsegs
++#define	dst_buf		dst.u.buf
++
++/*
++ *  Return values for hifn_crypto()
++ */
++#define HIFN_CRYPTO_SUCCESS	0
++#define HIFN_CRYPTO_BAD_INPUT	(-1)
++#define HIFN_CRYPTO_RINGS_FULL	(-2)
++
++/**************************************************************************
++ *
++ *  Function:  hifn_crypto
++ *
++ *  Purpose:   Called by external drivers to begin an encryption on the
++ *             HIFN board.
++ *
++ *  Blocking/Non-blocking Issues
++ *  ============================
++ *  The driver cannot block in hifn_crypto (no calls to tsleep) currently.
++ *  hifn_crypto() returns HIFN_CRYPTO_RINGS_FULL if there is not enough
++ *  room in any of the rings for the request to proceed.
++ *
++ *  Return Values
++ *  =============
++ *  0 for success, negative values on error
++ *
++ *  Defines for negative error codes are:
++ *  
++ *    HIFN_CRYPTO_BAD_INPUT  :  The passed in command had invalid settings.
++ *    HIFN_CRYPTO_RINGS_FULL :  All DMA rings were full and non-blocking
++ *                              behaviour was requested.
++ *
++ *************************************************************************/
++
++/*
++ * Convert back and forth from 'sid' to 'card' and 'session'
++ */
++#define HIFN_CARD(sid)		(((sid) & 0xf0000000) >> 28)
++#define HIFN_SESSION(sid)	((sid) & 0x000007ff)
++#define HIFN_SID(crd,ses)	(((crd) << 28) | ((ses) & 0x7ff))
++
++#endif /* _KERNEL */
++
++struct hifn_stats {
++	u_int64_t hst_ibytes;
++	u_int64_t hst_obytes;
++	u_int32_t hst_ipackets;
++	u_int32_t hst_opackets;
++	u_int32_t hst_invalid;
++	u_int32_t hst_nomem;		/* malloc or one of hst_nomem_* */
++	u_int32_t hst_abort;
++	u_int32_t hst_noirq;		/* IRQ for no reason */
++	u_int32_t hst_totbatch;		/* ops submitted w/o interrupt */
++	u_int32_t hst_maxbatch;		/* max ops submitted together */
++	u_int32_t hst_unaligned;	/* unaligned src caused copy */
++	/*
++	 * The following divides hst_nomem into more specific buckets.
++	 */
++	u_int32_t hst_nomem_map;	/* bus_dmamap_create failed */
++	u_int32_t hst_nomem_load;	/* bus_dmamap_load_* failed */
++	u_int32_t hst_nomem_mbuf;	/* MGET* failed */
++	u_int32_t hst_nomem_mcl;	/* MCLGET* failed */
++	u_int32_t hst_nomem_cr;		/* out of command/result descriptor */
++	u_int32_t hst_nomem_sd;		/* out of src/dst descriptors */
++};
++
++#endif /* __HIFN7751VAR_H__ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/hifnHIPP.c linux-2.6.23.16/crypto/ocf/hifn/hifnHIPP.c
+--- linux-2.6.23.16.old/crypto/ocf/hifn/hifnHIPP.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/hifnHIPP.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,420 @@
++/*-
++ * Driver for Hifn HIPP-I/II chipset
++ * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *   derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored by Hifn Inc.
++ *
++ */
++
++/*
++ * Driver for various Hifn encryption processors.
++ */
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/random.h>
++#include <linux/version.h>
++#include <linux/skbuff.h>
++#include <linux/uio.h>
++#include <linux/sysfs.h>
++#include <linux/miscdevice.h>
++#include <asm/io.h>
++
++#include <cryptodev.h>
++
++#include "hifnHIPPreg.h"
++#include "hifnHIPPvar.h"
++
++#if 1
++#define	DPRINTF(a...)	if (hipp_debug) { \
++							printk("%s: ", sc ? \
++								device_get_nameunit(sc->sc_dev) : "hifn"); \
++							printk(a); \
++						} else
++#else
++#define	DPRINTF(a...)
++#endif
++
++typedef int bus_size_t;
++
++static inline int
++pci_get_revid(struct pci_dev *dev)
++{
++	u8 rid = 0;
++	pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
++	return rid;
++}
++
++#define debug hipp_debug
++int hipp_debug = 0;
++module_param(hipp_debug, int, 0644);
++MODULE_PARM_DESC(hipp_debug, "Enable debug");
++
++int hipp_maxbatch = 1;
++module_param(hipp_maxbatch, int, 0644);
++MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
++
++static	int  hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
++static	void hipp_remove(struct pci_dev *dev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++static irqreturn_t hipp_intr(int irq, void *arg);
++#else
++static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
++#endif
++
++static int hipp_num_chips = 0;
++static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
++
++static	int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
++static	int hipp_freesession(device_t, u_int64_t);
++static	int hipp_process(device_t, struct cryptop *, int);
++
++static device_method_t hipp_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	hipp_newsession),
++	DEVMETHOD(cryptodev_freesession,hipp_freesession),
++	DEVMETHOD(cryptodev_process,	hipp_process),
++};
++
++static __inline u_int32_t
++READ_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg)
++{
++	u_int32_t v = readl(sc->sc_bar[barno] + reg);
++	//sc->sc_bar0_lastreg = (bus_size_t) -1;
++	return (v);
++}
++static __inline void
++WRITE_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg, u_int32_t val)
++{
++	writel(val, sc->sc_bar[barno] + reg);
++}
++
++#define READ_REG_0(sc, reg)         READ_REG(sc, 0, reg)
++#define WRITE_REG_0(sc, reg, val)   WRITE_REG(sc,0, reg, val)
++#define READ_REG_1(sc, reg)         READ_REG(sc, 1, reg)
++#define WRITE_REG_1(sc, reg, val)   WRITE_REG(sc,1, reg, val)
++
++static int
++hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
++{
++	return EINVAL;
++}
++
++static int
++hipp_freesession(device_t dev, u_int64_t tid)
++{
++	return EINVAL;
++}
++
++static int
++hipp_process(device_t dev, struct cryptop *crp, int hint)
++{
++	return EINVAL;
++}
++
++static const char*
++hipp_partname(struct hipp_softc *sc, char buf[128], size_t blen)
++{
++	char *n = NULL;
++
++	switch (pci_get_vendor(sc->sc_pcidev)) {
++	case PCI_VENDOR_HIFN:
++		switch (pci_get_device(sc->sc_pcidev)) {
++		case PCI_PRODUCT_HIFN_7855:	n = "Hifn 7855";
++		case PCI_PRODUCT_HIFN_8155:	n = "Hifn 8155";
++		case PCI_PRODUCT_HIFN_6500:	n = "Hifn 6500";
++		}
++	}
++
++	if(n==NULL) {
++		snprintf(buf, blen, "VID=%02x,PID=%02x",
++			 pci_get_vendor(sc->sc_pcidev),
++			 pci_get_device(sc->sc_pcidev));
++	} else {
++		buf[0]='\0';
++		strncat(buf, n, blen);
++	}
++	return buf;
++}
++
++struct hipp_fs_entry {
++	struct attribute attr;
++	/* other stuff */
++};
++
++
++static ssize_t
++cryptoid_show(struct device *dev,
++	      struct device_attribute *attr,
++	      char *buf)						
++{								
++	struct hipp_softc *sc;					
++
++	sc = pci_get_drvdata(to_pci_dev (dev));
++	return sprintf (buf, "%d\n", sc->sc_cid);
++}
++
++struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
++
++/*
++ * Attach an interface that successfully probed.
++ */
++static int
++hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++{
++	struct hipp_softc *sc = NULL;
++	int i;
++	//char rbase;
++	//u_int16_t ena;
++	int rev;
++	//int rseg;
++	int rc;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (pci_enable_device(dev) < 0)
++		return(-ENODEV);
++
++	if (pci_set_mwi(dev))
++		return(-ENODEV);
++
++	if (!dev->irq) {
++		printk("hifn: found device with no IRQ assigned. check BIOS settings!");
++		pci_disable_device(dev);
++		return(-ENODEV);
++	}
++
++	sc = (struct hipp_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
++	if (!sc)
++		return(-ENOMEM);
++	memset(sc, 0, sizeof(*sc));
++
++	softc_device_init(sc, "hifn-hipp", hipp_num_chips, hipp_methods);
++
++	sc->sc_pcidev = dev;
++	sc->sc_irq = -1;
++	sc->sc_cid = -1;
++	sc->sc_num = hipp_num_chips++;
++
++	if (sc->sc_num < HIPP_MAX_CHIPS)
++		hipp_chip_idx[sc->sc_num] = sc;
++
++	pci_set_drvdata(sc->sc_pcidev, sc);
++
++	spin_lock_init(&sc->sc_mtx);
++
++	/*
++	 * Setup PCI resources.
++	 * The READ_REG_0, WRITE_REG_0, READ_REG_1,
++	 * and WRITE_REG_1 macros throughout the driver are used
++	 * to permit better debugging.
++	 */
++	for(i=0; i<4; i++) {
++		unsigned long mem_start, mem_len;
++		mem_start = pci_resource_start(sc->sc_pcidev, i);
++		mem_len   = pci_resource_len(sc->sc_pcidev, i);
++		sc->sc_barphy[i] = (caddr_t)mem_start;
++		sc->sc_bar[i] = (ocf_iomem_t) ioremap(mem_start, mem_len);
++		if (!sc->sc_bar[i]) {
++			device_printf(sc->sc_dev, "cannot map bar%d register space\n", i);
++			goto fail;
++		}
++	}
++
++	//hipp_reset_board(sc, 0);
++	pci_set_master(sc->sc_pcidev);
++
++	/*
++	 * Arrange the interrupt line.
++	 */
++	rc = request_irq(dev->irq, hipp_intr, IRQF_SHARED, "hifn", sc);
++	if (rc) {
++		device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
++		goto fail;
++	}
++	sc->sc_irq = dev->irq;
++
++	rev = READ_REG_1(sc, HIPP_1_REVID) & 0xffff;
++
++	{
++		char b[32];
++		device_printf(sc->sc_dev, "%s, rev %u",
++			      hipp_partname(sc, b, sizeof(b)), rev);
++	}
++
++#if 0
++	if (sc->sc_flags & HIFN_IS_7956)
++		printf(", pll=0x%x<%s clk, %ux mult>",
++			sc->sc_pllconfig,
++			sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
++			2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
++#endif
++	printf("\n");
++
++	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
++	if (sc->sc_cid < 0) {
++		device_printf(sc->sc_dev, "could not get crypto driver id\n");
++		goto fail;
++	}
++
++#if 0 /* cannot work with a non-GPL module */
++	/* make a sysfs entry to let the world know what entry we got */
++	sysfs_create_file(&sc->sc_pcidev->dev.kobj, &hipp_dev_cryptoid.attr);
++#endif
++
++#if 0
++	init_timer(&sc->sc_tickto);
++	sc->sc_tickto.function = hifn_tick;
++	sc->sc_tickto.data = (unsigned long) sc->sc_num;
++	mod_timer(&sc->sc_tickto, jiffies + HZ);
++#endif
++
++#if 0 /* no code here yet ?? */
++	crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
++#endif
++
++	return (0);
++
++fail:
++	if (sc->sc_cid >= 0)
++		crypto_unregister_all(sc->sc_cid);
++	if (sc->sc_irq != -1)
++		free_irq(sc->sc_irq, sc);
++	
++#if 0
++	if (sc->sc_dma) {
++		/* Turn off DMA polling */
++		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++			    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++		
++		pci_free_consistent(sc->sc_pcidev,
++				    sizeof(*sc->sc_dma),
++				    sc->sc_dma, sc->sc_dma_physaddr);
++	}
++#endif
++	kfree(sc);
++	return (-ENXIO);
++}
++
++/*
++ * Detach an interface that successfully probed.
++ */
++static void
++hipp_remove(struct pci_dev *dev)
++{
++	struct hipp_softc *sc = pci_get_drvdata(dev);
++	unsigned long l_flags;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	/* disable interrupts */
++	HIPP_LOCK(sc);
++
++#if 0
++	WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
++	HIFN_UNLOCK(sc);
++
++	/*XXX other resources */
++	del_timer_sync(&sc->sc_tickto);
++
++	/* Turn off DMA polling */
++	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++#endif
++
++	crypto_unregister_all(sc->sc_cid);
++
++	free_irq(sc->sc_irq, sc);
++
++#if 0
++	pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
++                sc->sc_dma, sc->sc_dma_physaddr);
++#endif
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++static irqreturn_t hipp_intr(int irq, void *arg)
++#else
++static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs)
++#endif
++{
++	struct hipp_softc *sc = arg;
++
++	sc = sc; /* shut up compiler */
++
++	return IRQ_HANDLED;
++}
++
++static struct pci_device_id hipp_pci_tbl[] = {
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7855,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_8155,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++};
++MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
++
++static struct pci_driver hipp_driver = {
++	.name         = "hipp",
++	.id_table     = hipp_pci_tbl,
++	.probe        =	hipp_probe,
++	.remove       = hipp_remove,
++	/* add PM stuff here one day */
++};
++
++static int __init hipp_init (void)
++{
++	struct hipp_softc *sc = NULL;
++	int rc;
++
++	DPRINTF("%s(%p)\n", __FUNCTION__, hipp_init);
++
++	rc = pci_register_driver(&hipp_driver);
++	pci_register_driver_compat(&hipp_driver, rc);
++
++	return rc;
++}
++
++static void __exit hipp_exit (void)
++{
++	pci_unregister_driver(&hipp_driver);
++}
++
++module_init(hipp_init);
++module_exit(hipp_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
++MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/hifnHIPPreg.h linux-2.6.23.16/crypto/ocf/hifn/hifnHIPPreg.h
+--- linux-2.6.23.16.old/crypto/ocf/hifn/hifnHIPPreg.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/hifnHIPPreg.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,46 @@
++/*-
++ * Hifn HIPP-I/HIPP-II (7855/8155) driver.
++ * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored by Hifn inc.
++ *
++ */
++
++#ifndef __HIFNHIPP_H__
++#define	__HIFNHIPP_H__
++
++/*
++ * PCI vendor and device identifiers
++ */
++#define	PCI_VENDOR_HIFN		0x13a3		/* Hifn */
++#define	PCI_PRODUCT_HIFN_6500	0x0006		/* 6500 */
++#define	PCI_PRODUCT_HIFN_7855	0x001f		/* 7855 */
++#define	PCI_PRODUCT_HIFN_8155	0x999		/* XXX 8155 */
++
++#define HIPP_1_REVID            0x01 /* BOGUS */
++
++#endif /* __HIPP_H__ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/hifnHIPPvar.h linux-2.6.23.16/crypto/ocf/hifn/hifnHIPPvar.h
+--- linux-2.6.23.16.old/crypto/ocf/hifn/hifnHIPPvar.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/hifnHIPPvar.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,93 @@
++/*
++ * Hifn HIPP-I/HIPP-II (7855/8155) driver.
++ * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com> * 
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Effort sponsored by Hifn inc.
++ *
++ */
++
++#ifndef __HIFNHIPPVAR_H__
++#define __HIFNHIPPVAR_H__
++
++#define HIPP_MAX_CHIPS 8
++
++/*
++ * Holds data specific to a single Hifn HIPP-I board.
++ */
++struct hipp_softc {
++	softc_device_decl		 sc_dev;
++
++	struct pci_dev		*sc_pcidev;	/* device backpointer */
++	ocf_iomem_t             sc_bar[5];
++	caddr_t		        sc_barphy[5];   /* physical address */
++	int			sc_num;		/* for multiple devs */
++	spinlock_t		sc_mtx;		/* per-instance lock */
++	int32_t			sc_cid;
++	int			sc_irq;
++
++#if 0
++
++	u_int32_t		sc_dmaier;
++	u_int32_t		sc_drammodel;	/* 1=dram, 0=sram */
++	u_int32_t		sc_pllconfig;	/* 7954/7955/7956 PLL config */
++
++	struct hifn_dma		*sc_dma;
++	dma_addr_t		sc_dma_physaddr;/* physical address of sc_dma */
++
++	int			sc_dmansegs;
++	int			sc_maxses;
++	int			sc_nsessions;
++	struct hifn_session	*sc_sessions;
++	int			sc_ramsize;
++	int			sc_flags;
++#define	HIFN_HAS_RNG		0x1	/* includes random number generator */
++#define	HIFN_HAS_PUBLIC		0x2	/* includes public key support */
++#define	HIFN_HAS_AES		0x4	/* includes AES support */
++#define	HIFN_IS_7811		0x8	/* Hifn 7811 part */
++#define	HIFN_IS_7956		0x10	/* Hifn 7956/7955 don't have SDRAM */
++
++	struct timer_list	sc_tickto;	/* for managing DMA */
++
++	int			sc_rngfirst;
++	int			sc_rnghz;	/* RNG polling frequency */
++
++	int			sc_c_busy;	/* command ring busy */
++	int			sc_s_busy;	/* source data ring busy */
++	int			sc_d_busy;	/* destination data ring busy */
++	int			sc_r_busy;	/* result ring busy */
++	int			sc_active;	/* for initial countdown */
++	int			sc_needwakeup;	/* ops q'd wating on resources */
++	int			sc_curbatch;	/* # ops submitted w/o int */
++	int			sc_suspended;
++	struct miscdevice       sc_miscdev;
++#endif
++};
++
++#define	HIPP_LOCK(_sc)		spin_lock_irqsave(&(_sc)->sc_mtx, l_flags)
++#define	HIPP_UNLOCK(_sc)	spin_unlock_irqrestore(&(_sc)->sc_mtx, l_flags)
++
++#endif /* __HIFNHIPPVAR_H__ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/hifn/Makefile linux-2.6.23.16/crypto/ocf/hifn/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/hifn/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/hifn/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,13 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_HIFN)     += hifn7751.o
++obj-$(CONFIG_OCF_HIFNHIPP) += hifnHIPP.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/ixp4xx/ixp4xx.c linux-2.6.23.16/crypto/ocf/ixp4xx/ixp4xx.c
+--- linux-2.6.23.16.old/crypto/ocf/ixp4xx/ixp4xx.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/ixp4xx/ixp4xx.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,1324 @@
++/*
++ * An OCF module that uses Intels IXP CryptACC API to do the crypto.
++ * This driver requires the IXP400 Access Library that is available
++ * from Intel in order to operate (or compile).
++ *
++ * Written by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this product
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/crypto.h>
++#include <linux/interrupt.h>
++#include <asm/scatterlist.h>
++
++#include <IxTypes.h>
++#include <IxOsBuffMgt.h>
++#include <IxNpeDl.h>
++#include <IxCryptoAcc.h>
++#include <IxQMgr.h>
++#include <IxOsServices.h>
++#include <IxOsCacheMMU.h>
++
++#include <cryptodev.h>
++#include <uio.h>
++
++#ifndef IX_MBUF_PRIV
++#define IX_MBUF_PRIV(x) ((x)->priv)
++#endif
++
++struct ixp_data;
++
++struct ixp_q {
++	struct list_head	 ixp_q_list;
++	struct ixp_data		*ixp_q_data;
++	struct cryptop		*ixp_q_crp;
++	struct cryptodesc	*ixp_q_ccrd;
++	struct cryptodesc	*ixp_q_acrd;
++	IX_MBUF				 ixp_q_mbuf;
++	UINT8				*ixp_hash_dest; /* Location for hash in client buffer */
++	UINT8				*ixp_hash_src; /* Location of hash in internal buffer */
++	unsigned char		 ixp_q_iv_data[IX_CRYPTO_ACC_MAX_CIPHER_IV_LENGTH];
++	unsigned char		*ixp_q_iv;
++};
++
++struct ixp_data {
++	int					 ixp_registered;	/* is the context registered */
++	int					 ixp_crd_flags;		/* detect direction changes */
++
++	int					 ixp_cipher_alg;
++	int					 ixp_auth_alg;
++
++	UINT32				 ixp_ctx_id;
++	UINT32				 ixp_hash_key_id;	/* used when hashing */
++	IxCryptoAccCtx		 ixp_ctx;
++	IX_MBUF				 ixp_pri_mbuf;
++	IX_MBUF				 ixp_sec_mbuf;
++
++	struct work_struct   ixp_pending_work;
++	struct work_struct   ixp_registration_work;
++	struct list_head	 ixp_q;				/* unprocessed requests */
++};
++
++#ifdef __ixp46X
++
++#define	MAX_IOP_SIZE	64	/* words */
++#define	MAX_OOP_SIZE	128
++
++#define	MAX_PARAMS		3
++
++struct ixp_pkq {
++	struct list_head			 pkq_list;
++	struct cryptkop				*pkq_krp;
++
++	IxCryptoAccPkeEauInOperands	 pkq_op;
++	IxCryptoAccPkeEauOpResult	 pkq_result;
++
++	UINT32						 pkq_ibuf0[MAX_IOP_SIZE];
++	UINT32						 pkq_ibuf1[MAX_IOP_SIZE];
++	UINT32						 pkq_ibuf2[MAX_IOP_SIZE];
++	UINT32						 pkq_obuf[MAX_OOP_SIZE];
++};
++
++static LIST_HEAD(ixp_pkq); /* current PK wait list */
++static struct ixp_pkq *ixp_pk_cur;
++static spinlock_t ixp_pkq_lock;
++
++#endif /* __ixp46X */
++
++static int ixp_blocked = 0;
++
++static int32_t			 ixp_id = -1;
++static struct ixp_data **ixp_sessions = NULL;
++static u_int32_t		 ixp_sesnum = 0;
++
++static int ixp_process(device_t, struct cryptop *, int);
++static int ixp_newsession(device_t, u_int32_t *, struct cryptoini *);
++static int ixp_freesession(device_t, u_int64_t);
++#ifdef __ixp46X
++static int ixp_kprocess(device_t, struct cryptkop *krp, int hint);
++#endif
++
++static struct kmem_cache *qcache;
++
++#define debug ixp_debug
++static int ixp_debug = 0;
++module_param(ixp_debug, int, 0644);
++MODULE_PARM_DESC(ixp_debug, "Enable debug");
++
++static int ixp_init_crypto = 1;
++module_param(ixp_init_crypto, int, 0444); /* RO after load/boot */
++MODULE_PARM_DESC(ixp_init_crypto, "Call ixCryptoAccInit (default is 1)");
++
++static void ixp_process_pending(void *arg);
++static void ixp_registration(void *arg);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void ixp_process_pending_wq(struct work_struct *work);
++static void ixp_registration_wq(struct work_struct *work);
++#endif
++
++/*
++ * dummy device structure
++ */
++
++static struct {
++	softc_device_decl	sc_dev;
++} ixpdev;
++
++static device_method_t ixp_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	ixp_newsession),
++	DEVMETHOD(cryptodev_freesession,ixp_freesession),
++	DEVMETHOD(cryptodev_process,	ixp_process),
++#ifdef __ixp46X
++	DEVMETHOD(cryptodev_kprocess,	ixp_kprocess),
++#endif
++};
++
++/*
++ * Generate a new software session.
++ */
++static int
++ixp_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
++{
++	struct ixp_data *ixp;
++	u_int32_t i;
++#define AUTH_LEN(cri, def) \
++	(cri->cri_mlen ? cri->cri_mlen : (def))
++
++	dprintk("%s():alg %d\n", __FUNCTION__,cri->cri_alg);
++	if (sid == NULL || cri == NULL) {
++		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	if (ixp_sessions) {
++		for (i = 1; i < ixp_sesnum; i++)
++			if (ixp_sessions[i] == NULL)
++				break;
++	} else
++		i = 1;		/* NB: to silence compiler warning */
++
++	if (ixp_sessions == NULL || i == ixp_sesnum) {
++		struct ixp_data **ixpd;
++
++		if (ixp_sessions == NULL) {
++			i = 1; /* We leave ixp_sessions[0] empty */
++			ixp_sesnum = CRYPTO_SW_SESSIONS;
++		} else
++			ixp_sesnum *= 2;
++
++		ixpd = kmalloc(ixp_sesnum * sizeof(struct ixp_data *), SLAB_ATOMIC);
++		if (ixpd == NULL) {
++			/* Reset session number */
++			if (ixp_sesnum == CRYPTO_SW_SESSIONS)
++				ixp_sesnum = 0;
++			else
++				ixp_sesnum /= 2;
++			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++			return ENOBUFS;
++		}
++		memset(ixpd, 0, ixp_sesnum * sizeof(struct ixp_data *));
++
++		/* Copy existing sessions */
++		if (ixp_sessions) {
++			memcpy(ixpd, ixp_sessions,
++			    (ixp_sesnum / 2) * sizeof(struct ixp_data *));
++			kfree(ixp_sessions);
++		}
++
++		ixp_sessions = ixpd;
++	}
++
++	ixp_sessions[i] = (struct ixp_data *) kmalloc(sizeof(struct ixp_data),
++			SLAB_ATOMIC);
++	if (ixp_sessions[i] == NULL) {
++		ixp_freesession(NULL, i);
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return ENOBUFS;
++	}
++
++	*sid = i;
++
++	ixp = ixp_sessions[i];
++	memset(ixp, 0, sizeof(*ixp));
++
++	ixp->ixp_cipher_alg = -1;
++	ixp->ixp_auth_alg = -1;
++	ixp->ixp_ctx_id = -1;
++	INIT_LIST_HEAD(&ixp->ixp_q);
++
++	ixp->ixp_ctx.useDifferentSrcAndDestMbufs = 0;
++
++	while (cri) {
++		switch (cri->cri_alg) {
++		case CRYPTO_DES_CBC:
++			ixp->ixp_cipher_alg = cri->cri_alg;
++			ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_DES;
++			ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
++			ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
++			ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
++			ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
++						IX_CRYPTO_ACC_DES_IV_64;
++			memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
++					cri->cri_key, (cri->cri_klen + 7) / 8);
++			break;
++
++		case CRYPTO_3DES_CBC:
++			ixp->ixp_cipher_alg = cri->cri_alg;
++			ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
++			ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
++			ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
++			ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
++			ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
++						IX_CRYPTO_ACC_DES_IV_64;
++			memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
++					cri->cri_key, (cri->cri_klen + 7) / 8);
++			break;
++
++		case CRYPTO_RIJNDAEL128_CBC:
++			ixp->ixp_cipher_alg = cri->cri_alg;
++			ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_AES;
++			ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
++			ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
++			ixp->ixp_ctx.cipherCtx.cipherBlockLen = 16;
++			ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen = 16;
++			memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
++					cri->cri_key, (cri->cri_klen + 7) / 8);
++			break;
++
++		case CRYPTO_MD5:
++		case CRYPTO_MD5_HMAC:
++			ixp->ixp_auth_alg = cri->cri_alg;
++			ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_MD5;
++			ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, MD5_HASH_LEN);
++			ixp->ixp_ctx.authCtx.aadLen = 0;
++			/* Only MD5_HMAC needs a key */
++			if (cri->cri_alg == CRYPTO_MD5_HMAC) {
++				ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
++				if (ixp->ixp_ctx.authCtx.authKeyLen >
++						sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
++					printk(
++						"ixp4xx: Invalid key length for MD5_HMAC - %d bits\n",
++							cri->cri_klen);
++					ixp_freesession(NULL, i);
++					return EINVAL;
++				}
++				memcpy(ixp->ixp_ctx.authCtx.key.authKey,
++						cri->cri_key, (cri->cri_klen + 7) / 8);
++			}
++			break;
++
++		case CRYPTO_SHA1:
++		case CRYPTO_SHA1_HMAC:
++			ixp->ixp_auth_alg = cri->cri_alg;
++			ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
++			ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, SHA1_HASH_LEN);
++			ixp->ixp_ctx.authCtx.aadLen = 0;
++			/* Only SHA1_HMAC needs a key */
++			if (cri->cri_alg == CRYPTO_SHA1_HMAC) {
++				ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
++				if (ixp->ixp_ctx.authCtx.authKeyLen >
++						sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
++					printk(
++						"ixp4xx: Invalid key length for SHA1_HMAC - %d bits\n",
++							cri->cri_klen);
++					ixp_freesession(NULL, i);
++					return EINVAL;
++				}
++				memcpy(ixp->ixp_ctx.authCtx.key.authKey,
++						cri->cri_key, (cri->cri_klen + 7) / 8);
++			}
++			break;
++
++		default:
++			printk("ixp: unknown algo 0x%x\n", cri->cri_alg);
++			ixp_freesession(NULL, i);
++			return EINVAL;
++		}
++		cri = cri->cri_next;
++	}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++	INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending_wq);
++	INIT_WORK(&ixp->ixp_registration_work, ixp_registration_wq);
++#else
++	INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending, ixp);
++	INIT_WORK(&ixp->ixp_registration_work, ixp_registration, ixp);
++#endif
++
++	return 0;
++}
++
++
++/*
++ * Free a session.
++ */
++static int
++ixp_freesession(device_t dev, u_int64_t tid)
++{
++	u_int32_t sid = CRYPTO_SESID2LID(tid);
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid > ixp_sesnum || ixp_sessions == NULL ||
++			ixp_sessions[sid] == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	/* Silently accept and return */
++	if (sid == 0)
++		return 0;
++
++	if (ixp_sessions[sid]) {
++		if (ixp_sessions[sid]->ixp_ctx_id != -1) {
++			ixCryptoAccCtxUnregister(ixp_sessions[sid]->ixp_ctx_id);
++			ixp_sessions[sid]->ixp_ctx_id = -1;
++		}
++
++		flush_scheduled_work();
++
++		kfree(ixp_sessions[sid]);
++	}
++	ixp_sessions[sid] = NULL;
++	if (ixp_blocked) {
++		ixp_blocked = 0;
++		crypto_unblock(ixp_id, CRYPTO_SYMQ);
++	}
++	return 0;
++}
++
++
++/*
++ * callback for when hash processing is complete
++ */
++
++static void
++ixp_hash_perform_cb(
++	UINT32 hash_key_id,
++	IX_MBUF *bufp,
++	IxCryptoAccStatus status)
++{
++	struct ixp_q *q;
++
++	dprintk("%s(%u, %p, 0x%x)\n", __FUNCTION__, hash_key_id, bufp, status);
++
++	if (bufp == NULL) {
++		printk("ixp: NULL buf in %s\n", __FUNCTION__);
++		return;
++	}
++
++	q = IX_MBUF_PRIV(bufp);
++	if (q == NULL) {
++		printk("ixp: NULL priv in %s\n", __FUNCTION__);
++		return;
++	}
++
++	if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
++		/* On success, need to copy hash back into original client buffer */
++		memcpy(q->ixp_hash_dest, q->ixp_hash_src,
++				(q->ixp_q_data->ixp_auth_alg == CRYPTO_SHA1) ?
++					SHA1_HASH_LEN : MD5_HASH_LEN);
++	}
++	else {
++		printk("ixp: hash perform failed status=%d\n", status);
++		q->ixp_q_crp->crp_etype = EINVAL;
++	}
++
++	/* Free internal buffer used for hashing */
++	kfree(IX_MBUF_MDATA(&q->ixp_q_mbuf));
++
++	crypto_done(q->ixp_q_crp);
++	kmem_cache_free(qcache, q);
++}
++
++/*
++ * setup a request and perform it
++ */
++static void
++ixp_q_process(struct ixp_q *q)
++{
++	IxCryptoAccStatus status;
++	struct ixp_data *ixp = q->ixp_q_data;
++	int auth_off = 0;
++	int auth_len = 0;
++	int crypt_off = 0;
++	int crypt_len = 0;
++	int icv_off = 0;
++	char *crypt_func;
++
++	dprintk("%s(%p)\n", __FUNCTION__, q);
++
++	if (q->ixp_q_ccrd) {
++		if (q->ixp_q_ccrd->crd_flags & CRD_F_IV_EXPLICIT) {
++			q->ixp_q_iv = q->ixp_q_ccrd->crd_iv;
++		} else {
++			q->ixp_q_iv = q->ixp_q_iv_data;
++			crypto_copydata(q->ixp_q_crp->crp_flags, q->ixp_q_crp->crp_buf,
++					q->ixp_q_ccrd->crd_inject,
++					ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen,
++					(caddr_t) q->ixp_q_iv);
++		}
++
++		if (q->ixp_q_acrd) {
++			auth_off = q->ixp_q_acrd->crd_skip;
++			auth_len = q->ixp_q_acrd->crd_len;
++			icv_off  = q->ixp_q_acrd->crd_inject;
++		}
++
++		crypt_off = q->ixp_q_ccrd->crd_skip;
++		crypt_len = q->ixp_q_ccrd->crd_len;
++	} else { /* if (q->ixp_q_acrd) */
++		auth_off = q->ixp_q_acrd->crd_skip;
++		auth_len = q->ixp_q_acrd->crd_len;
++		icv_off  = q->ixp_q_acrd->crd_inject;
++	}
++
++	if (q->ixp_q_crp->crp_flags & CRYPTO_F_SKBUF) {
++		struct sk_buff *skb = (struct sk_buff *) q->ixp_q_crp->crp_buf;
++		if (skb_shinfo(skb)->nr_frags) {
++			/*
++			 * DAVIDM fix this limitation one day by using
++			 * a buffer pool and chaining,  it is not currently
++			 * needed for current user/kernel space acceleration
++			 */
++			printk("ixp: Cannot handle fragmented skb's yet !\n");
++			q->ixp_q_crp->crp_etype = ENOENT;
++			goto done;
++		}
++		IX_MBUF_MLEN(&q->ixp_q_mbuf) =
++				IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) =  skb->len;
++		IX_MBUF_MDATA(&q->ixp_q_mbuf) = skb->data;
++	} else if (q->ixp_q_crp->crp_flags & CRYPTO_F_IOV) {
++		struct uio *uiop = (struct uio *) q->ixp_q_crp->crp_buf;
++		if (uiop->uio_iovcnt != 1) {
++			/*
++			 * DAVIDM fix this limitation one day by using
++			 * a buffer pool and chaining,  it is not currently
++			 * needed for current user/kernel space acceleration
++			 */
++			printk("ixp: Cannot handle more than 1 iovec yet !\n");
++			q->ixp_q_crp->crp_etype = ENOENT;
++			goto done;
++		}
++		IX_MBUF_MLEN(&q->ixp_q_mbuf) =
++				IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_len;
++		IX_MBUF_MDATA(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_base;
++	} else /* contig buffer */ {
++		IX_MBUF_MLEN(&q->ixp_q_mbuf)  =
++				IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_ilen;
++		IX_MBUF_MDATA(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_buf;
++	}
++
++	IX_MBUF_PRIV(&q->ixp_q_mbuf) = q;
++
++	if (ixp->ixp_auth_alg == CRYPTO_SHA1 || ixp->ixp_auth_alg == CRYPTO_MD5) {
++		/*
++		 * For SHA1 and MD5 hash, need to create an internal buffer that is big
++		 * enough to hold the original data + the appropriate padding for the
++		 * hash algorithm.
++		 */
++		UINT8 *tbuf = NULL;
++
++		IX_MBUF_MLEN(&q->ixp_q_mbuf) = IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) =
++			((IX_MBUF_MLEN(&q->ixp_q_mbuf) * 8) + 72 + 511) / 8;
++		tbuf = kmalloc(IX_MBUF_MLEN(&q->ixp_q_mbuf), SLAB_ATOMIC);
++		
++		if (IX_MBUF_MDATA(&q->ixp_q_mbuf) == NULL) {
++			printk("ixp: kmalloc(%u, SLAB_ATOMIC) failed\n",
++					IX_MBUF_MLEN(&q->ixp_q_mbuf));
++			q->ixp_q_crp->crp_etype = ENOMEM;
++			goto done;
++		}
++		memcpy(tbuf, &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off], auth_len);
++
++		/* Set location in client buffer to copy hash into */
++		q->ixp_hash_dest =
++			&(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off + auth_len];
++
++		IX_MBUF_MDATA(&q->ixp_q_mbuf) = tbuf;
++
++		/* Set location in internal buffer for where hash starts */
++		q->ixp_hash_src = &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_len];
++
++		crypt_func = "ixCryptoAccHashPerform";
++		status = ixCryptoAccHashPerform(ixp->ixp_ctx.authCtx.authAlgo,
++				&q->ixp_q_mbuf, ixp_hash_perform_cb, 0, auth_len, auth_len,
++				&ixp->ixp_hash_key_id);
++	}
++	else {
++		crypt_func = "ixCryptoAccAuthCryptPerform";
++		status = ixCryptoAccAuthCryptPerform(ixp->ixp_ctx_id, &q->ixp_q_mbuf,
++			NULL, auth_off, auth_len, crypt_off, crypt_len, icv_off,
++			q->ixp_q_iv);
++	}
++
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
++		return;
++
++	if (IX_CRYPTO_ACC_STATUS_QUEUE_FULL == status) {
++		q->ixp_q_crp->crp_etype = ENOMEM;
++		goto done;
++	}
++
++	printk("ixp: %s failed %u\n", crypt_func, status);
++	q->ixp_q_crp->crp_etype = EINVAL;
++
++done:
++	crypto_done(q->ixp_q_crp);
++	kmem_cache_free(qcache, q);
++}
++
++
++/*
++ * because we cannot process the Q from the Register callback
++ * we do it here on a task Q.
++ */
++
++static void
++ixp_process_pending(void *arg)
++{
++	struct ixp_data *ixp = arg;
++	struct ixp_q *q = NULL;
++
++	dprintk("%s(%p)\n", __FUNCTION__, arg);
++
++	if (!ixp)
++		return;
++
++	while (!list_empty(&ixp->ixp_q)) {
++		q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
++		list_del(&q->ixp_q_list);
++		ixp_q_process(q);
++	}
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void
++ixp_process_pending_wq(struct work_struct *work)
++{
++	struct ixp_data *ixp = container_of(work, struct ixp_data,
++								ixp_pending_work);
++	ixp_process_pending(ixp);
++}
++#endif
++
++/*
++ * callback for when context registration is complete
++ */
++
++static void
++ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
++{
++	int i;
++	struct ixp_data *ixp;
++	struct ixp_q *q;
++
++	dprintk("%s(%d, %p, %d)\n", __FUNCTION__, ctx_id, bufp, status);
++
++	/*
++	 * free any buffer passed in to this routine
++	 */
++	if (bufp) {
++		IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
++		kfree(IX_MBUF_MDATA(bufp));
++		IX_MBUF_MDATA(bufp) = NULL;
++	}
++
++	for (i = 0; i < ixp_sesnum; i++) {
++		ixp = ixp_sessions[i];
++		if (ixp && ixp->ixp_ctx_id == ctx_id)
++			break;
++	}
++	if (i >= ixp_sesnum) {
++		printk("ixp: invalid context id %d\n", ctx_id);
++		return;
++	}
++
++	if (IX_CRYPTO_ACC_STATUS_WAIT == status) {
++		/* this is normal to free the first of two buffers */
++		dprintk("ixp: register not finished yet.\n");
++		return;
++	}
++
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
++		printk("ixp: register failed 0x%x\n", status);
++		while (!list_empty(&ixp->ixp_q)) {
++			q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
++			list_del(&q->ixp_q_list);
++			q->ixp_q_crp->crp_etype = EINVAL;
++			crypto_done(q->ixp_q_crp);
++			kmem_cache_free(qcache, q);
++		}
++		return;
++	}
++
++	/*
++	 * we are now registered,  we cannot start processing the Q here
++	 * or we get strange errors with AES (DES/3DES seem to be ok).
++	 */
++	ixp->ixp_registered = 1;
++	schedule_work(&ixp->ixp_pending_work);
++}
++
++
++/*
++ * callback for when data processing is complete
++ */
++
++static void
++ixp_perform_cb(
++	UINT32 ctx_id,
++	IX_MBUF *sbufp,
++	IX_MBUF *dbufp,
++	IxCryptoAccStatus status)
++{
++	struct ixp_q *q;
++
++	dprintk("%s(%d, %p, %p, 0x%x)\n", __FUNCTION__, ctx_id, sbufp,
++			dbufp, status);
++
++	if (sbufp == NULL) {
++		printk("ixp: NULL sbuf in ixp_perform_cb\n");
++		return;
++	}
++
++	q = IX_MBUF_PRIV(sbufp);
++	if (q == NULL) {
++		printk("ixp: NULL priv in ixp_perform_cb\n");
++		return;
++	}
++
++	if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
++		printk("ixp: perform failed status=%d\n", status);
++		q->ixp_q_crp->crp_etype = EINVAL;
++	}
++
++	crypto_done(q->ixp_q_crp);
++	kmem_cache_free(qcache, q);
++}
++
++
++/*
++ * registration is not callable at IRQ time,  so we defer
++ * to a task queue,  this routines completes the registration for us
++ * when the task queue runs
++ *
++ * Unfortunately this means we cannot tell OCF that the driver is blocked,
++ * we do that on the next request.
++ */
++
++static void
++ixp_registration(void *arg)
++{
++	struct ixp_data *ixp = arg;
++	struct ixp_q *q = NULL;
++	IX_MBUF *pri = NULL, *sec = NULL;
++	int status = IX_CRYPTO_ACC_STATUS_SUCCESS;
++
++	if (!ixp) {
++		printk("ixp: ixp_registration with no arg\n");
++		return;
++	}
++
++	if (ixp->ixp_ctx_id != -1) {
++		ixCryptoAccCtxUnregister(ixp->ixp_ctx_id);
++		ixp->ixp_ctx_id = -1;
++	}
++
++	if (list_empty(&ixp->ixp_q)) {
++		printk("ixp: ixp_registration with no Q\n");
++		return;
++	}
++
++	/*
++	 * setup the primary and secondary buffers
++	 */
++	q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
++	if (q->ixp_q_acrd) {
++		pri = &ixp->ixp_pri_mbuf;
++		sec = &ixp->ixp_sec_mbuf;
++		IX_MBUF_MLEN(pri)  = IX_MBUF_PKT_LEN(pri) = 128;
++		IX_MBUF_MDATA(pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
++		IX_MBUF_MLEN(sec)  = IX_MBUF_PKT_LEN(sec) = 128;
++		IX_MBUF_MDATA(sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
++	}
++
++	/* Only need to register if a crypt op or HMAC op */
++	if (!(ixp->ixp_auth_alg == CRYPTO_SHA1 ||
++				ixp->ixp_auth_alg == CRYPTO_MD5)) {
++		status = ixCryptoAccCtxRegister(
++					&ixp->ixp_ctx,
++					pri, sec,
++					ixp_register_cb,
++					ixp_perform_cb,
++					&ixp->ixp_ctx_id);
++	}
++	else {
++		/* Otherwise we start processing pending q */
++		schedule_work(&ixp->ixp_pending_work);
++	}
++
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
++		return;
++
++	if (IX_CRYPTO_ACC_STATUS_EXCEED_MAX_TUNNELS == status) {
++		printk("ixp: ixCryptoAccCtxRegister failed (out of tunnels)\n");
++		ixp_blocked = 1;
++		/* perhaps we should return EGAIN on queued ops ? */
++		return;
++	}
++
++	printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
++	ixp->ixp_ctx_id = -1;
++
++	/*
++	 * everything waiting is toasted
++	 */
++	while (!list_empty(&ixp->ixp_q)) {
++		q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
++		list_del(&q->ixp_q_list);
++		q->ixp_q_crp->crp_etype = ENOENT;
++		crypto_done(q->ixp_q_crp);
++		kmem_cache_free(qcache, q);
++	}
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void
++ixp_registration_wq(struct work_struct *work)
++{
++	struct ixp_data *ixp = container_of(work, struct ixp_data,
++								ixp_registration_work);
++	ixp_registration(ixp);
++}
++#endif
++
++/*
++ * Process a request.
++ */
++static int
++ixp_process(device_t dev, struct cryptop *crp, int hint)
++{
++	struct ixp_data *ixp;
++	unsigned int lid;
++	struct ixp_q *q = NULL;
++	int status;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	/* Sanity check */
++	if (crp == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	crp->crp_etype = 0;
++
++	if (ixp_blocked)
++		return ERESTART;
++
++	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		crp->crp_etype = EINVAL;
++		goto done;
++	}
++
++	/*
++	 * find the session we are using
++	 */
++
++	lid = crp->crp_sid & 0xffffffff;
++	if (lid >= ixp_sesnum || lid == 0 || ixp_sessions == NULL ||
++			ixp_sessions[lid] == NULL) {
++		crp->crp_etype = ENOENT;
++		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
++		goto done;
++	}
++	ixp = ixp_sessions[lid];
++
++	/*
++	 * setup a new request ready for queuing
++	 */
++	q = kmem_cache_alloc(qcache, SLAB_ATOMIC);
++	if (q == NULL) {
++		dprintk("%s,%d: ENOMEM\n", __FILE__, __LINE__);
++		crp->crp_etype = ENOMEM;
++		goto done;
++	}
++	/*
++	 * save some cycles by only zeroing the important bits
++	 */
++	memset(&q->ixp_q_mbuf, 0, sizeof(q->ixp_q_mbuf));
++	q->ixp_q_ccrd = NULL;
++	q->ixp_q_acrd = NULL;
++	q->ixp_q_crp = crp;
++	q->ixp_q_data = ixp;
++
++	/*
++	 * point the cipher and auth descriptors appropriately
++	 * check that we have something to do
++	 */
++	if (crp->crp_desc->crd_alg == ixp->ixp_cipher_alg)
++		q->ixp_q_ccrd = crp->crp_desc;
++	else if (crp->crp_desc->crd_alg == ixp->ixp_auth_alg)
++		q->ixp_q_acrd = crp->crp_desc;
++	else {
++		crp->crp_etype = ENOENT;
++		dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
++		goto done;
++	}
++	if (crp->crp_desc->crd_next) {
++		if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_cipher_alg)
++			q->ixp_q_ccrd = crp->crp_desc->crd_next;
++		else if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_auth_alg)
++			q->ixp_q_acrd = crp->crp_desc->crd_next;
++		else {
++			crp->crp_etype = ENOENT;
++			dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
++			goto done;
++		}
++	}
++
++	/*
++	 * If there is a direction change for this context then we mark it as
++	 * unregistered and re-register is for the new direction.  This is not
++	 * a very expensive operation and currently only tends to happen when
++	 * user-space application are doing benchmarks
++	 *
++	 * DM - we should be checking for pending requests before unregistering.
++	 */
++	if (q->ixp_q_ccrd && ixp->ixp_registered &&
++			ixp->ixp_crd_flags != (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT)) {
++		dprintk("%s - detected direction change on session\n", __FUNCTION__);
++		ixp->ixp_registered = 0;
++	}
++
++	/*
++	 * if we are registered,  call straight into the perform code
++	 */
++	if (ixp->ixp_registered) {
++		ixp_q_process(q);
++		return 0;
++	}
++
++	/*
++	 * the only part of the context not set in newsession is the direction
++	 * dependent parts
++	 */
++	if (q->ixp_q_ccrd) {
++		ixp->ixp_crd_flags = (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT);
++		if (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT) {
++			ixp->ixp_ctx.operation = q->ixp_q_acrd ?
++					IX_CRYPTO_ACC_OP_ENCRYPT_AUTH : IX_CRYPTO_ACC_OP_ENCRYPT;
++		} else {
++			ixp->ixp_ctx.operation = q->ixp_q_acrd ?
++					IX_CRYPTO_ACC_OP_AUTH_DECRYPT : IX_CRYPTO_ACC_OP_DECRYPT;
++		}
++	} else {
++		/* q->ixp_q_acrd must be set if we are here */
++		ixp->ixp_ctx.operation = IX_CRYPTO_ACC_OP_AUTH_CALC;
++	}
++
++	status = list_empty(&ixp->ixp_q);
++	list_add_tail(&q->ixp_q_list, &ixp->ixp_q);
++	if (status)
++		schedule_work(&ixp->ixp_registration_work);
++	return 0;
++
++done:
++	if (q)
++		kmem_cache_free(qcache, q);
++	crypto_done(crp);
++	return 0;
++}
++
++
++#ifdef __ixp46X
++/*
++ * key processing support for the ixp465
++ */
++
++
++/*
++ * copy a BN (LE) into a buffer (BE) an fill out the op appropriately
++ * assume zeroed and only copy bits that are significant
++ */
++
++static int
++ixp_copy_ibuf(struct crparam *p, IxCryptoAccPkeEauOperand *op, UINT32 *buf)
++{
++	unsigned char *src = (unsigned char *) p->crp_p;
++	unsigned char *dst;
++	int len, bits = p->crp_nbits;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	if (bits > MAX_IOP_SIZE * sizeof(UINT32) * 8) {
++		dprintk("%s - ibuf too big (%d > %d)\n", __FUNCTION__,
++				bits, MAX_IOP_SIZE * sizeof(UINT32) * 8);
++		return -1;
++	}
++
++	len = (bits + 31) / 32; /* the number UINT32's needed */
++
++	dst = (unsigned char *) &buf[len];
++	dst--;
++
++	while (bits > 0) {
++		*dst-- = *src++;
++		bits -= 8;
++	}
++
++#if 0 /* no need to zero remaining bits as it is done during request alloc */
++	while (dst > (unsigned char *) buf)
++		*dst-- = '\0';
++#endif
++
++	op->pData = buf;
++	op->dataLen = len;
++	return 0;
++}
++
++/*
++ * copy out the result,  be as forgiving as we can about small output buffers
++ */
++
++static int
++ixp_copy_obuf(struct crparam *p, IxCryptoAccPkeEauOpResult *op, UINT32 *buf)
++{
++	unsigned char *dst = (unsigned char *) p->crp_p;
++	unsigned char *src = (unsigned char *) buf;
++	int len, z, bits = p->crp_nbits;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	len = op->dataLen * sizeof(UINT32);
++
++	/* skip leading zeroes to be small buffer friendly */
++	z = 0;
++	while (z < len && src[z] == '\0')
++		z++;
++
++	src += len;
++	src--;
++	len -= z;
++
++	while (len > 0 && bits > 0) {
++		*dst++ = *src--;
++		len--;
++		bits -= 8;
++	}
++
++	while (bits > 0) {
++		*dst++ = '\0';
++		bits -= 8;
++	}
++
++	if (len > 0) {
++		dprintk("%s - obuf is %d (z=%d, ob=%d) bytes too small\n",
++				__FUNCTION__, len, z, p->crp_nbits / 8);
++		return -1;
++	}
++
++	return 0;
++}
++
++
++/*
++ * the parameter offsets for exp_mod
++ */
++
++#define IXP_PARAM_BASE 0
++#define IXP_PARAM_EXP  1
++#define IXP_PARAM_MOD  2
++#define IXP_PARAM_RES  3
++
++/*
++ * key processing complete callback,  is also used to start processing
++ * by passing a NULL for pResult
++ */
++
++static void
++ixp_kperform_cb(
++	IxCryptoAccPkeEauOperation operation,
++	IxCryptoAccPkeEauOpResult *pResult,
++	BOOL carryOrBorrow,
++	IxCryptoAccStatus status)
++{
++	struct ixp_pkq *q, *tmp;
++	unsigned long flags;
++
++	dprintk("%s(0x%x, %p, %d, 0x%x)\n", __FUNCTION__, operation, pResult,
++			carryOrBorrow, status);
++
++	/* handle a completed request */
++	if (pResult) {
++		if (ixp_pk_cur && &ixp_pk_cur->pkq_result == pResult) {
++			q = ixp_pk_cur;
++			if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
++				dprintk("%s() - op failed 0x%x\n", __FUNCTION__, status);
++				q->pkq_krp->krp_status = ERANGE; /* could do better */
++			} else {
++				/* copy out the result */
++				if (ixp_copy_obuf(&q->pkq_krp->krp_param[IXP_PARAM_RES],
++						&q->pkq_result, q->pkq_obuf))
++					q->pkq_krp->krp_status = ERANGE;
++			}
++			crypto_kdone(q->pkq_krp);
++			kfree(q);
++			ixp_pk_cur = NULL;
++		} else
++			printk("%s - callback with invalid result pointer\n", __FUNCTION__);
++	}
++
++	spin_lock_irqsave(&ixp_pkq_lock, flags);
++	if (ixp_pk_cur || list_empty(&ixp_pkq)) {
++		spin_unlock_irqrestore(&ixp_pkq_lock, flags);
++		return;
++	}
++
++	list_for_each_entry_safe(q, tmp, &ixp_pkq, pkq_list) {
++
++		list_del(&q->pkq_list);
++		ixp_pk_cur = q;
++
++		spin_unlock_irqrestore(&ixp_pkq_lock, flags);
++
++		status = ixCryptoAccPkeEauPerform(
++				IX_CRYPTO_ACC_OP_EAU_MOD_EXP,
++				&q->pkq_op,
++				ixp_kperform_cb,
++				&q->pkq_result);
++	
++		if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
++			dprintk("%s() - ixCryptoAccPkeEauPerform SUCCESS\n", __FUNCTION__);
++			return; /* callback will return here for callback */
++		} else if (status == IX_CRYPTO_ACC_STATUS_RETRY) {
++			printk("%s() - ixCryptoAccPkeEauPerform RETRY\n", __FUNCTION__);
++		} else {
++			printk("%s() - ixCryptoAccPkeEauPerform failed %d\n",
++					__FUNCTION__, status);
++		}
++		q->pkq_krp->krp_status = ERANGE; /* could do better */
++		crypto_kdone(q->pkq_krp);
++		kfree(q);
++		spin_lock_irqsave(&ixp_pkq_lock, flags);
++	}
++	spin_unlock_irqrestore(&ixp_pkq_lock, flags);
++}
++
++
++static int
++ixp_kprocess(device_t dev, struct cryptkop *krp, int hint)
++{
++	struct ixp_pkq *q;
++	int rc = 0;
++	unsigned long flags;
++
++	dprintk("%s l1=%d l2=%d l3=%d l4=%d\n", __FUNCTION__,
++			krp->krp_param[IXP_PARAM_BASE].crp_nbits,
++			krp->krp_param[IXP_PARAM_EXP].crp_nbits,
++			krp->krp_param[IXP_PARAM_MOD].crp_nbits,
++			krp->krp_param[IXP_PARAM_RES].crp_nbits);
++
++
++	if (krp->krp_op != CRK_MOD_EXP) {
++		krp->krp_status = EOPNOTSUPP;
++		goto err;
++	}
++
++	q = (struct ixp_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
++	if (q == NULL) {
++		krp->krp_status = ENOMEM;
++		goto err;
++	}
++
++	/*
++	 * The PKE engine does not appear to zero the output buffer
++	 * appropriately, so we need to do it all here.
++	 */
++	memset(q, 0, sizeof(*q));
++
++	q->pkq_krp = krp;
++	INIT_LIST_HEAD(&q->pkq_list);
++
++	if (ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_BASE], &q->pkq_op.modExpOpr.M,
++			q->pkq_ibuf0))
++		rc = 1;
++	if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_EXP],
++				&q->pkq_op.modExpOpr.e, q->pkq_ibuf1))
++		rc = 2;
++	if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_MOD],
++				&q->pkq_op.modExpOpr.N, q->pkq_ibuf2))
++		rc = 3;
++
++	if (rc) {
++		kfree(q);
++		krp->krp_status = ERANGE;
++		goto err;
++	}
++
++	q->pkq_result.pData           = q->pkq_obuf;
++	q->pkq_result.dataLen         =
++			(krp->krp_param[IXP_PARAM_RES].crp_nbits + 31) / 32;
++
++	spin_lock_irqsave(&ixp_pkq_lock, flags);
++	list_add_tail(&q->pkq_list, &ixp_pkq);
++	spin_unlock_irqrestore(&ixp_pkq_lock, flags);
++
++	if (!ixp_pk_cur)
++		ixp_kperform_cb(0, NULL, 0, 0);
++	return (0);
++
++err:
++	crypto_kdone(krp);
++	return (0);
++}
++
++
++
++#ifdef CONFIG_OCF_RANDOMHARVEST
++/*
++ * We run the random number generator output through SHA so that it
++ * is FIPS compliant.
++ */
++
++static volatile int sha_done = 0;
++static unsigned char sha_digest[20];
++
++static void
++ixp_hash_cb(UINT8 *digest, IxCryptoAccStatus status)
++{
++	dprintk("%s(%p, %d)\n", __FUNCTION__, digest, status);
++	if (sha_digest != digest)
++		printk("digest error\n");
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
++		sha_done = 1;
++	else
++		sha_done = -status;
++}
++
++static int
++ixp_read_random(void *arg, u_int32_t *buf, int maxwords)
++{
++	IxCryptoAccStatus status;
++	int i, n, rc;
++
++	dprintk("%s(%p, %d)\n", __FUNCTION__, buf, maxwords);
++	memset(buf, 0, maxwords * sizeof(*buf));
++	status = ixCryptoAccPkePseudoRandomNumberGet(maxwords, buf);
++	if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
++		dprintk("%s: ixCryptoAccPkePseudoRandomNumberGet failed %d\n",
++				__FUNCTION__, status);
++		return 0;
++	}
++
++	/*
++	 * run the random data through SHA to make it look more random
++	 */
++
++	n = sizeof(sha_digest); /* process digest bytes at a time */
++
++	rc = 0;
++	for (i = 0; i < maxwords; i += n / sizeof(*buf)) {
++		if ((maxwords - i) * sizeof(*buf) < n)
++			n = (maxwords - i) * sizeof(*buf);
++		sha_done = 0;
++		status = ixCryptoAccPkeHashPerform(IX_CRYPTO_ACC_AUTH_SHA1,
++				(UINT8 *) &buf[i], n, ixp_hash_cb, sha_digest);
++		if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
++			dprintk("ixCryptoAccPkeHashPerform failed %d\n", status);
++			return -EIO;
++		}
++		while (!sha_done)
++			schedule();
++		if (sha_done < 0) {
++			dprintk("ixCryptoAccPkeHashPerform failed CB %d\n", -sha_done);
++			return 0;
++		}
++		memcpy(&buf[i], sha_digest, n);
++		rc += n / sizeof(*buf);;
++	}
++
++	return rc;
++}
++#endif /* CONFIG_OCF_RANDOMHARVEST */
++
++#endif /* __ixp46X */
++
++
++
++/*
++ * our driver startup and shutdown routines
++ */
++
++static int
++ixp_init(void)
++{
++	dprintk("%s(%p)\n", __FUNCTION__, ixp_init);
++
++	if (ixp_init_crypto && ixCryptoAccInit() != IX_CRYPTO_ACC_STATUS_SUCCESS)
++		printk("ixCryptoAccInit failed, assuming already initialised!\n");
++
++	qcache = kmem_cache_create("ixp4xx_q", sizeof(struct ixp_q), 0,
++				SLAB_HWCACHE_ALIGN, NULL
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
++				, NULL
++#endif
++				  );
++	if (!qcache) {
++		printk("failed to create Qcache\n");
++		return -ENOENT;
++	}
++
++	memset(&ixpdev, 0, sizeof(ixpdev));
++	softc_device_init(&ixpdev, "ixp4xx", 0, ixp_methods);
++
++	ixp_id = crypto_get_driverid(softc_get_device(&ixpdev),
++				CRYPTOCAP_F_HARDWARE);
++	if (ixp_id < 0)
++		panic("IXP/OCF crypto device cannot initialize!");
++
++#define	REGISTER(alg) \
++	crypto_register(ixp_id,alg,0,0)
++
++	REGISTER(CRYPTO_DES_CBC);
++	REGISTER(CRYPTO_3DES_CBC);
++	REGISTER(CRYPTO_RIJNDAEL128_CBC);
++#ifdef CONFIG_OCF_IXP4XX_SHA1_MD5
++	REGISTER(CRYPTO_MD5);
++	REGISTER(CRYPTO_SHA1);
++#endif
++	REGISTER(CRYPTO_MD5_HMAC);
++	REGISTER(CRYPTO_SHA1_HMAC);
++#undef REGISTER
++
++#ifdef __ixp46X
++	spin_lock_init(&ixp_pkq_lock);
++	/*
++	 * we do not enable the go fast options here as they can potentially
++	 * allow timing based attacks
++	 *
++	 * http://www.openssl.org/news/secadv_20030219.txt
++	 */
++	ixCryptoAccPkeEauExpConfig(0, 0);
++	crypto_kregister(ixp_id, CRK_MOD_EXP, 0);
++#ifdef CONFIG_OCF_RANDOMHARVEST
++	crypto_rregister(ixp_id, ixp_read_random, NULL);
++#endif
++#endif
++
++	return 0;
++}
++
++static void
++ixp_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	crypto_unregister_all(ixp_id);
++	ixp_id = -1;
++	kmem_cache_destroy(qcache);
++	qcache = NULL;
++}
++
++module_init(ixp_init);
++module_exit(ixp_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("David McCullough <dmccullough@cyberguard.com>");
++MODULE_DESCRIPTION("ixp (OCF module for IXP4xx crypto)");
+diff -urN linux-2.6.23.16.old/crypto/ocf/ixp4xx/Makefile linux-2.6.23.16/crypto/ocf/ixp4xx/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/ixp4xx/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/ixp4xx/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,104 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++#
++# You will need to point this at your Intel ixp425 includes,  this portion
++# of the Makefile only really works under SGLinux with the appropriate libs
++# installed.  They can be downloaded from http://www.snapgear.org/
++#
++ifeq ($(CONFIG_CPU_IXP46X),y)
++IXPLATFORM = ixp46X
++else
++ifeq ($(CONFIG_CPU_IXP43X),y)
++IXPLATFORM = ixp43X
++else
++IXPLATFORM = ixp42X
++endif
++endif
++
++ifdef CONFIG_IXP400_LIB_2_4
++IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.4/ixp400_xscale_sw
++OSAL_DIR     = $(ROOTDIR)/modules/ixp425/ixp400-2.4/ixp_osal
++endif
++ifdef CONFIG_IXP400_LIB_2_1
++IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.1/ixp400_xscale_sw
++OSAL_DIR     = $(ROOTDIR)/modules/ixp425/ixp400-2.1/ixp_osal
++endif
++ifdef CONFIG_IXP400_LIB_2_0
++IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.0/ixp400_xscale_sw
++OSAL_DIR     = $(ROOTDIR)/modules/ixp425/ixp400-2.0/ixp_osal
++endif
++ifdef IX_XSCALE_SW
++ifdef CONFIG_IXP400_LIB_2_4
++IXP_CFLAGS = \
++	-I$(ROOTDIR)/. \
++	-I$(IX_XSCALE_SW)/src/include \
++	-I$(OSAL_DIR)/common/include/ \
++	-I$(OSAL_DIR)/common/include/modules/ \
++	-I$(OSAL_DIR)/common/include/modules/ddk/ \
++	-I$(OSAL_DIR)/common/include/modules/bufferMgt/ \
++	-I$(OSAL_DIR)/common/include/modules/ioMem/ \
++	-I$(OSAL_DIR)/common/os/linux/include/ \
++	-I$(OSAL_DIR)/common/os/linux/include/core/  \
++	-I$(OSAL_DIR)/common/os/linux/include/modules/ \
++	-I$(OSAL_DIR)/common/os/linux/include/modules/ddk/ \
++	-I$(OSAL_DIR)/common/os/linux/include/modules/bufferMgt/ \
++	-I$(OSAL_DIR)/common/os/linux/include/modules/ioMem/ \
++	-I$(OSAL_DIR)/platforms/$(IXPLATFORM)/include/ \
++	-I$(OSAL_DIR)/platforms/$(IXPLATFORM)/os/linux/include/ \
++	-DENABLE_IOMEM -DENABLE_BUFFERMGT -DENABLE_DDK \
++	-DUSE_IXP4XX_CRYPTO
++else
++IXP_CFLAGS = \
++	-I$(ROOTDIR)/. \
++	-I$(IX_XSCALE_SW)/src/include \
++	-I$(OSAL_DIR)/ \
++	-I$(OSAL_DIR)/os/linux/include/ \
++	-I$(OSAL_DIR)/os/linux/include/modules/ \
++	-I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \
++	-I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \
++	-I$(OSAL_DIR)/os/linux/include/core/  \
++	-I$(OSAL_DIR)/os/linux/include/platforms/ \
++	-I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \
++	-I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp425 \
++	-I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp465 \
++	-I$(OSAL_DIR)/os/linux/include/core/ \
++	-I$(OSAL_DIR)/include/ \
++	-I$(OSAL_DIR)/include/modules/ \
++	-I$(OSAL_DIR)/include/modules/bufferMgt/ \
++	-I$(OSAL_DIR)/include/modules/ioMem/ \
++	-I$(OSAL_DIR)/include/platforms/ \
++	-I$(OSAL_DIR)/include/platforms/ixp400/ \
++	-DUSE_IXP4XX_CRYPTO
++endif
++endif
++ifdef CONFIG_IXP400_LIB_1_4
++IXP_CFLAGS   = \
++	-I$(ROOTDIR)/. \
++	-I$(ROOTDIR)/modules/ixp425/ixp400-1.4/ixp400_xscale_sw/src/include \
++	-I$(ROOTDIR)/modules/ixp425/ixp400-1.4/ixp400_xscale_sw/src/linux \
++	-DUSE_IXP4XX_CRYPTO
++endif
++ifndef IXPDIR
++IXPDIR = ixp-version-is-not-supported
++endif
++
++ifeq ($(CONFIG_CPU_IXP46X),y)
++IXP_CFLAGS += -D__ixp46X
++else
++ifeq ($(CONFIG_CPU_IXP43X),y)
++IXP_CFLAGS += -D__ixp43X
++else
++IXP_CFLAGS += -D__ixp42X
++endif
++endif
++
++obj-$(CONFIG_OCF_IXP4XX) += ixp4xx.o
++
++obj ?= .
++EXTRA_CFLAGS += $(IXP_CFLAGS) -I$(obj)/.. -I$(obj)/.
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/Kconfig linux-2.6.23.16/crypto/ocf/Kconfig
+--- linux-2.6.23.16.old/crypto/ocf/Kconfig	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/Kconfig	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,95 @@
++menu "OCF Configuration"
++
++config OCF_OCF
++	tristate "OCF (Open Cryptograhic Framework)"
++	help
++	  A linux port of the OpenBSD/FreeBSD crypto framework.
++
++config OCF_RANDOMHARVEST
++	tristate "crypto random --- harvest entropy for /dev/random"
++	depends on OCF_OCF
++	help
++	  Includes code to harvest random numbers from devices that support it.
++
++config OCF_FIPS
++	tristate "enable fips RNG checks"
++	depends on OCF_OCF && OCF_RANDOMHARVEST
++	help
++	  Run all RNG provided data through a fips check before
++	  adding it /dev/random's entropy pool.
++
++config OCF_CRYPTODEV
++	tristate "cryptodev (user space support)"
++	depends on OCF_OCF
++	help
++	  The user space API to access crypto hardware.
++
++config OCF_CRYPTOSOFT
++	tristate "cryptosoft (software crypto engine)"
++	depends on OCF_OCF
++	help
++	  A software driver for the OCF framework that uses
++	  the kernel CryptoAPI.
++
++config OCF_SAFE
++	tristate "safenet (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  A driver for a number of the safenet Excel crypto accelerators.
++	  Currently tested and working on the 1141 and 1741.
++
++config OCF_IXP4XX
++	tristate "IXP4xx (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  XScale IXP4xx crypto accelerator driver.  Requires the
++	  Intel Access library.
++
++config OCF_IXP4XX_SHA1_MD5
++	bool "IXP4xx SHA1 and MD5 Hashing"
++	depends on OCF_IXP4XX
++	help
++	  Allows the IXP4xx crypto accelerator to perform SHA1 and MD5 hashing.
++	  Note: this is MUCH slower than using cryptosoft (software crypto engine).
++
++config OCF_HIFN
++	tristate "hifn (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for various HIFN based crypto accelerators.
++	  (7951, 7955, 7956, 7751, 7811)
++
++config OCF_HIFNHIPP
++	tristate "Hifn HIPP (HW packet crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for various HIFN (HIPP) based crypto accelerators
++	  (7855)
++
++config OCF_TALITOS
++	tristate "talitos (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for Freescale's security engine (SEC/talitos).
++
++config OCF_PASEMI
++        tristate "pasemi (HW crypto engine)"
++        depends on OCF_OCF && PPC_PASEMI
++        help
++          OCF driver for for PA Semi PWRficient DMA Engine
++
++config OCF_OCFNULL
++	tristate "ocfnull (fake crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for measuring ipsec overheads (does no crypto)
++
++config OCF_BENCH
++	tristate "ocf-bench (HW crypto in-kernel benchmark)"
++	depends on OCF_OCF
++	help
++	  A very simple encryption test for the in-kernel interface
++	  of OCF.  Also includes code to benchmark the IXP Access library
++	  for comparison.
++
++endmenu
+diff -urN linux-2.6.23.16.old/crypto/ocf/Makefile linux-2.6.23.16/crypto/ocf/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,120 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++OCF_OBJS = crypto.o criov.o
++
++ifdef CONFIG_OCF_RANDOMHARVEST
++	OCF_OBJS += random.o
++endif
++
++ifdef CONFIG_OCF_FIPS
++	OCF_OBJS += rndtest.o
++endif
++
++# Add in autoconf.h to get #defines for CONFIG_xxx
++AUTOCONF_H=$(ROOTDIR)/modules/autoconf.h
++ifeq ($(AUTOCONF_H), $(wildcard $(AUTOCONF_H)))
++	EXTRA_CFLAGS += -include $(AUTOCONF_H)
++	export EXTRA_CFLAGS
++endif
++
++ifndef obj
++	obj ?= .
++	_obj = subdir
++	mod-subdirs := safe hifn ixp4xx talitos ocfnull
++	export-objs += crypto.o criov.o random.o
++	list-multi += ocf.o
++	_slash :=
++else
++	_obj = obj
++	_slash := /
++endif
++
++EXTRA_CFLAGS += -I$(obj)/.
++
++obj-$(CONFIG_OCF_OCF)         += ocf.o
++obj-$(CONFIG_OCF_CRYPTODEV)   += cryptodev.o
++obj-$(CONFIG_OCF_CRYPTOSOFT)  += cryptosoft.o
++obj-$(CONFIG_OCF_BENCH)       += ocf-bench.o
++
++$(_obj)-$(CONFIG_OCF_SAFE)    += safe$(_slash)
++$(_obj)-$(CONFIG_OCF_HIFN)    += hifn$(_slash)
++$(_obj)-$(CONFIG_OCF_IXP4XX)  += ixp4xx$(_slash)
++$(_obj)-$(CONFIG_OCF_TALITOS) += talitos$(_slash)
++$(_obj)-$(CONFIG_OCF_PASEMI)  += pasemi$(_slash)
++$(_obj)-$(CONFIG_OCF_OCFNULL) += ocfnull$(_slash)
++
++ocf-objs := $(OCF_OBJS)
++
++$(list-multi) dummy1: $(ocf-objs)
++	$(LD) -r -o $@ $(ocf-objs)
++
++.PHONY:
++clean:
++	rm -f *.o *.ko .*.o.flags .*.ko.cmd .*.o.cmd .*.mod.o.cmd *.mod.c
++	rm -f */*.o */*.ko */.*.o.cmd */.*.ko.cmd */.*.mod.o.cmd */*.mod.c */.*.o.flags
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
++#
++# release gen targets
++#
++
++.PHONY: patch
++patch:
++	REL=`date +%Y%m%d`; \
++		patch=ocf-linux-$$REL.patch; \
++		patch24=ocf-linux-24-$$REL.patch; \
++		patch26=ocf-linux-26-$$REL.patch; \
++		( \
++			find . -name Makefile; \
++			find . -name Config.in; \
++			find . -name Kconfig; \
++			find . -name README; \
++			find . -name '*.[ch]' | grep -v '.mod.c'; \
++		) | while read t; do \
++			diff -Nau /dev/null $$t | sed 's?^+++ \./?+++ linux/crypto/ocf/?'; \
++		done > $$patch; \
++		cat patches/linux-2.4.35-ocf.patch $$patch > $$patch24; \
++		cat patches/linux-2.6.23-ocf.patch $$patch > $$patch26
++
++.PHONY: tarball
++tarball:
++	REL=`date +%Y%m%d`; RELDIR=/tmp/ocf-linux-$$REL; \
++		CURDIR=`pwd`; \
++		rm -rf /tmp/ocf-linux-$$REL*; \
++		mkdir -p $$RELDIR/tools; \
++		cp README* $$RELDIR; \
++		cp patches/openss*.patch $$RELDIR; \
++		cp patches/crypto-tools.patch $$RELDIR; \
++		cp tools/[!C]* $$RELDIR/tools; \
++		cd ..; \
++		tar cvf $$RELDIR/ocf-linux.tar \
++					--exclude=CVS \
++					--exclude=.* \
++					--exclude=*.o \
++					--exclude=*.ko \
++					--exclude=*.mod.* \
++					--exclude=README* \
++					--exclude=ocf-*.patch \
++					--exclude=ocf/patches/openss*.patch \
++					--exclude=ocf/patches/crypto-tools.patch \
++					--exclude=ocf/tools \
++					ocf; \
++		gzip -9 $$RELDIR/ocf-linux.tar; \
++		cd /tmp; \
++		tar cvf ocf-linux-$$REL.tar ocf-linux-$$REL; \
++		gzip -9 ocf-linux-$$REL.tar; \
++		cd $$CURDIR/../../user; \
++		rm -rf /tmp/crypto-tools-$$REL*; \
++		tar cvf /tmp/crypto-tools-$$REL.tar \
++					--exclude=CVS \
++					--exclude=.* \
++					--exclude=*.o \
++					--exclude=cryptotest \
++					--exclude=cryptokeytest \
++					crypto-tools; \
++		gzip -9 /tmp/crypto-tools-$$REL.tar
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/ocf-bench.c linux-2.6.23.16/crypto/ocf/ocf-bench.c
+--- linux-2.6.23.16.old/crypto/ocf/ocf-bench.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/ocf-bench.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,436 @@
++/*
++ * A loadable module that benchmarks the OCF crypto speed from kernel space.
++ *
++ * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com>
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this product
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ */
++
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/version.h>
++#include <linux/interrupt.h>
++#include <cryptodev.h>
++
++#ifdef I_HAVE_AN_XSCALE_WITH_INTEL_SDK
++#define BENCH_IXP_ACCESS_LIB 1
++#endif
++#ifdef BENCH_IXP_ACCESS_LIB
++#include <IxTypes.h>
++#include <IxOsBuffMgt.h>
++#include <IxNpeDl.h>
++#include <IxCryptoAcc.h>
++#include <IxQMgr.h>
++#include <IxOsServices.h>
++#include <IxOsCacheMMU.h>
++#endif
++
++/*
++ * support for access lib version 1.4
++ */
++#ifndef IX_MBUF_PRIV
++#define IX_MBUF_PRIV(x) ((x)->priv)
++#endif
++
++/*
++ * the number of simultaneously active requests
++ */
++static int request_q_len = 20;
++module_param(request_q_len, int, 0);
++MODULE_PARM_DESC(request_q_len, "Number of outstanding requests");
++/*
++ * how many requests we want to have processed
++ */
++static int request_num = 1024;
++module_param(request_num, int, 0);
++MODULE_PARM_DESC(request_num, "run for at least this many requests");
++/*
++ * the size of each request
++ */
++static int request_size = 1500;
++module_param(request_size, int, 0);
++MODULE_PARM_DESC(request_size, "size of each request");
++
++/*
++ * a structure for each request
++ */
++typedef struct  {
++	struct work_struct work;
++#ifdef BENCH_IXP_ACCESS_LIB
++	IX_MBUF mbuf;
++#endif
++	unsigned char *buffer;
++} request_t;
++
++static request_t *requests;
++
++static int outstanding;
++static int total;
++
++/*************************************************************************/
++/*
++ * OCF benchmark routines
++ */
++
++static uint64_t ocf_cryptoid;
++static int ocf_init(void);
++static int ocf_cb(struct cryptop *crp);
++static void ocf_request(void *arg);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void ocf_request_wq(struct work_struct *work);
++#endif
++
++static int
++ocf_init(void)
++{
++	int error;
++	struct cryptoini crie, cria;
++	struct cryptodesc crda, crde;
++
++	memset(&crie, 0, sizeof(crie));
++	memset(&cria, 0, sizeof(cria));
++	memset(&crde, 0, sizeof(crde));
++	memset(&crda, 0, sizeof(crda));
++
++	cria.cri_alg  = CRYPTO_SHA1_HMAC;
++	cria.cri_klen = 20 * 8;
++	cria.cri_key  = "0123456789abcdefghij";
++
++	crie.cri_alg  = CRYPTO_3DES_CBC;
++	crie.cri_klen = 24 * 8;
++	crie.cri_key  = "0123456789abcdefghijklmn";
++
++	crie.cri_next = &cria;
++
++	error = crypto_newsession(&ocf_cryptoid, &crie, 0);
++	if (error) {
++		printk("crypto_newsession failed %d\n", error);
++		return -1;
++	}
++	return 0;
++}
++
++static int
++ocf_cb(struct cryptop *crp)
++{
++	request_t *r = (request_t *) crp->crp_opaque;
++
++	if (crp->crp_etype)
++		printk("Error in OCF processing: %d\n", crp->crp_etype);
++	total++;
++	crypto_freereq(crp);
++	crp = NULL;
++
++	if (total > request_num) {
++		outstanding--;
++		return 0;
++	}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++	INIT_WORK(&r->work, ocf_request_wq);
++#else
++	INIT_WORK(&r->work, ocf_request, r);
++#endif
++	schedule_work(&r->work);
++	return 0;
++}
++
++
++static void
++ocf_request(void *arg)
++{
++	request_t *r = arg;
++	struct cryptop *crp = crypto_getreq(2);
++	struct cryptodesc *crde, *crda;
++
++	if (!crp) {
++		outstanding--;
++		return;
++	}
++
++	crde = crp->crp_desc;
++	crda = crde->crd_next;
++
++	crda->crd_skip = 0;
++	crda->crd_flags = 0;
++	crda->crd_len = request_size;
++	crda->crd_inject = request_size;
++	crda->crd_alg = CRYPTO_SHA1_HMAC;
++	crda->crd_key = "0123456789abcdefghij";
++	crda->crd_klen = 20 * 8;
++
++	crde->crd_skip = 0;
++	crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_ENCRYPT;
++	crde->crd_len = request_size;
++	crde->crd_inject = request_size;
++	crde->crd_alg = CRYPTO_3DES_CBC;
++	crde->crd_key = "0123456789abcdefghijklmn";
++	crde->crd_klen = 24 * 8;
++
++	crp->crp_ilen = request_size + 64;
++	crp->crp_flags = CRYPTO_F_CBIMM;
++	crp->crp_buf = (caddr_t) r->buffer;
++	crp->crp_callback = ocf_cb;
++	crp->crp_sid = ocf_cryptoid;
++	crp->crp_opaque = (caddr_t) r;
++	crypto_dispatch(crp);
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void
++ocf_request_wq(struct work_struct *work)
++{
++	request_t *r = container_of(work, request_t, work);
++	ocf_request(r);
++}
++#endif
++
++/*************************************************************************/
++#ifdef BENCH_IXP_ACCESS_LIB
++/*************************************************************************/
++/*
++ * CryptoAcc benchmark routines
++ */
++
++static IxCryptoAccCtx ixp_ctx;
++static UINT32 ixp_ctx_id;
++static IX_MBUF ixp_pri;
++static IX_MBUF ixp_sec;
++static int ixp_registered = 0;
++
++static void ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp,
++					IxCryptoAccStatus status);
++static void ixp_perform_cb(UINT32 ctx_id, IX_MBUF *sbufp, IX_MBUF *dbufp,
++					IxCryptoAccStatus status);
++static void ixp_request(void *arg);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void ixp_request_wq(struct work_struct *work);
++#endif
++
++static int
++ixp_init(void)
++{
++	IxCryptoAccStatus status;
++
++	ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
++	ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
++	ixp_ctx.cipherCtx.cipherKeyLen = 24;
++	ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
++	ixp_ctx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_DES_IV_64;
++	memcpy(ixp_ctx.cipherCtx.key.cipherKey, "0123456789abcdefghijklmn", 24);
++
++	ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
++	ixp_ctx.authCtx.authDigestLen = 12;
++	ixp_ctx.authCtx.aadLen = 0;
++	ixp_ctx.authCtx.authKeyLen = 20;
++	memcpy(ixp_ctx.authCtx.key.authKey, "0123456789abcdefghij", 20);
++
++	ixp_ctx.useDifferentSrcAndDestMbufs = 0;
++	ixp_ctx.operation = IX_CRYPTO_ACC_OP_ENCRYPT_AUTH ;
++
++	IX_MBUF_MLEN(&ixp_pri)  = IX_MBUF_PKT_LEN(&ixp_pri) = 128;
++	IX_MBUF_MDATA(&ixp_pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
++	IX_MBUF_MLEN(&ixp_sec)  = IX_MBUF_PKT_LEN(&ixp_sec) = 128;
++	IX_MBUF_MDATA(&ixp_sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
++
++	status = ixCryptoAccCtxRegister(&ixp_ctx, &ixp_pri, &ixp_sec,
++			ixp_register_cb, ixp_perform_cb, &ixp_ctx_id);
++
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status) {
++		while (!ixp_registered)
++			schedule();
++		return ixp_registered < 0 ? -1 : 0;
++	}
++
++	printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
++	return -1;
++}
++
++static void
++ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
++{
++	if (bufp) {
++		IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
++		kfree(IX_MBUF_MDATA(bufp));
++		IX_MBUF_MDATA(bufp) = NULL;
++	}
++
++	if (IX_CRYPTO_ACC_STATUS_WAIT == status)
++		return;
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
++		ixp_registered = 1;
++	else
++		ixp_registered = -1;
++}
++
++static void
++ixp_perform_cb(
++	UINT32 ctx_id,
++	IX_MBUF *sbufp,
++	IX_MBUF *dbufp,
++	IxCryptoAccStatus status)
++{
++	request_t *r = NULL;
++
++	total++;
++	if (total > request_num) {
++		outstanding--;
++		return;
++	}
++
++	if (!sbufp || !(r = IX_MBUF_PRIV(sbufp))) {
++		printk("crappo %p %p\n", sbufp, r);
++		outstanding--;
++		return;
++	}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++	INIT_WORK(&r->work, ixp_request_wq);
++#else
++	INIT_WORK(&r->work, ixp_request, r);
++#endif
++	schedule_work(&r->work);
++}
++
++static void
++ixp_request(void *arg)
++{
++	request_t *r = arg;
++	IxCryptoAccStatus status;
++
++	memset(&r->mbuf, 0, sizeof(r->mbuf));
++	IX_MBUF_MLEN(&r->mbuf) = IX_MBUF_PKT_LEN(&r->mbuf) = request_size + 64;
++	IX_MBUF_MDATA(&r->mbuf) = r->buffer;
++	IX_MBUF_PRIV(&r->mbuf) = r;
++	status = ixCryptoAccAuthCryptPerform(ixp_ctx_id, &r->mbuf, NULL,
++			0, request_size, 0, request_size, request_size, r->buffer);
++	if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
++		printk("status1 = %d\n", status);
++		outstanding--;
++		return;
++	}
++	return;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void
++ixp_request_wq(struct work_struct *work)
++{
++	request_t *r = container_of(work, request_t, work);
++	ixp_request(r);
++}
++#endif
++
++/*************************************************************************/
++#endif /* BENCH_IXP_ACCESS_LIB */
++/*************************************************************************/
++
++int
++ocfbench_init(void)
++{
++	int i, jstart, jstop;
++
++	printk("Crypto Speed tests\n");
++
++	requests = kmalloc(sizeof(request_t) * request_q_len, GFP_KERNEL);
++	if (!requests) {
++		printk("malloc failed\n");
++		return -EINVAL;
++	}
++
++	for (i = 0; i < request_q_len; i++) {
++		/* +64 for return data */
++		requests[i].buffer = kmalloc(request_size + 128, GFP_DMA);
++		if (!requests[i].buffer) {
++			printk("malloc failed\n");
++			return -EINVAL;
++		}
++		memset(requests[i].buffer, '0' + i, request_size + 128);
++	}
++
++	/*
++	 * OCF benchmark
++	 */
++	printk("OCF: testing ...\n");
++	ocf_init();
++	total = outstanding = 0;
++	jstart = jiffies;
++	for (i = 0; i < request_q_len; i++) {
++		outstanding++;
++		ocf_request(&requests[i]);
++	}
++	while (outstanding > 0)
++		schedule();
++	jstop = jiffies;
++
++	printk("OCF: %d requests of %d bytes in %d jiffies\n", total, request_size,
++			jstop - jstart);
++
++#ifdef BENCH_IXP_ACCESS_LIB
++	/*
++	 * IXP benchmark
++	 */
++	printk("IXP: testing ...\n");
++	ixp_init();
++	total = outstanding = 0;
++	jstart = jiffies;
++	for (i = 0; i < request_q_len; i++) {
++		outstanding++;
++		ixp_request(&requests[i]);
++	}
++	while (outstanding > 0)
++		schedule();
++	jstop = jiffies;
++
++	printk("IXP: %d requests of %d bytes in %d jiffies\n", total, request_size,
++			jstop - jstart);
++#endif /* BENCH_IXP_ACCESS_LIB */
++
++	for (i = 0; i < request_q_len; i++)
++		kfree(requests[i].buffer);
++	kfree(requests);
++	return -EINVAL; /* always fail to load so it can be re-run quickly ;-) */
++}
++
++static void __exit ocfbench_exit(void)
++{
++}
++
++module_init(ocfbench_init);
++module_exit(ocfbench_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("Benchmark various in-kernel crypto speeds");
+diff -urN linux-2.6.23.16.old/crypto/ocf/ocf-compat.h linux-2.6.23.16/crypto/ocf/ocf-compat.h
+--- linux-2.6.23.16.old/crypto/ocf/ocf-compat.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/ocf-compat.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,249 @@
++#ifndef _BSD_COMPAT_H_
++#define _BSD_COMPAT_H_ 1
++/****************************************************************************/
++/*
++ * Provide compat routines for older linux kernels and BSD kernels
++ *
++ * Written by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2007 David McCullough <david_mccullough@securecomputing.com>
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this file
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ */
++/****************************************************************************/
++#ifdef __KERNEL__
++/*
++ * fake some BSD driver interface stuff specifically for OCF use
++ */
++
++typedef struct ocf_device *device_t;
++
++typedef struct {
++	int (*cryptodev_newsession)(device_t dev, u_int32_t *sidp, struct cryptoini *cri);
++	int (*cryptodev_freesession)(device_t dev, u_int64_t tid);
++	int (*cryptodev_process)(device_t dev, struct cryptop *crp, int hint);
++	int (*cryptodev_kprocess)(device_t dev, struct cryptkop *krp, int hint);
++} device_method_t;
++#define DEVMETHOD(id, func)	id: func
++
++struct ocf_device {
++	char name[32];		/* the driver name */
++	char nameunit[32];	/* the driver name + HW instance */
++	int  unit;
++	device_method_t	methods;
++	void *softc;
++};
++
++#define CRYPTODEV_NEWSESSION(dev, sid, cri) \
++	((*(dev)->methods.cryptodev_newsession)(dev,sid,cri))
++#define CRYPTODEV_FREESESSION(dev, sid) \
++	((*(dev)->methods.cryptodev_freesession)(dev, sid))
++#define CRYPTODEV_PROCESS(dev, crp, hint) \
++	((*(dev)->methods.cryptodev_process)(dev, crp, hint))
++#define CRYPTODEV_KPROCESS(dev, krp, hint) \
++	((*(dev)->methods.cryptodev_kprocess)(dev, krp, hint))
++
++#define device_get_name(dev)	((dev)->name)
++#define device_get_nameunit(dev)	((dev)->nameunit)
++#define device_get_unit(dev)	((dev)->unit)
++#define device_get_softc(dev)	((dev)->softc)
++
++#define	softc_device_decl \
++		struct ocf_device _device; \
++		device_t
++
++#define	softc_device_init(_sc, _name, _unit, _methods) \
++	if (1) {\
++	strncpy((_sc)->_device.name, _name, sizeof((_sc)->_device.name) - 1); \
++	snprintf((_sc)->_device.nameunit, sizeof((_sc)->_device.name), "%s%d", _name, _unit); \
++	(_sc)->_device.unit = _unit; \
++	(_sc)->_device.methods = _methods; \
++	(_sc)->_device.softc = (void *) _sc; \
++	*(device_t *)((softc_get_device(_sc))+1) = &(_sc)->_device; \
++	} else
++
++#define	softc_get_device(_sc)	(&(_sc)->_device)
++
++/*
++ * iomem support for 2.4 and 2.6 kernels
++ */
++#include <linux/version.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++#define ocf_iomem_t	unsigned long
++
++/*
++ * implement simple workqueue like support for older kernels
++ */
++
++#include <linux/tqueue.h>
++
++#define work_struct tq_struct
++
++#define INIT_WORK(wp, fp, ap) \
++	do { \
++		(wp)->sync = 0; \
++		(wp)->routine = (fp); \
++		(wp)->data = (ap); \
++	} while (0)
++
++#define schedule_work(wp) \
++	do { \
++		queue_task((wp), &tq_immediate); \
++		mark_bh(IMMEDIATE_BH); \
++	} while (0)
++
++#define flush_scheduled_work()	run_task_queue(&tq_immediate)
++
++#else
++#define ocf_iomem_t	void __iomem *
++
++#include <linux/workqueue.h>
++
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
++#define files_fdtable(files)	(files)
++#endif
++
++#ifdef MODULE_PARM
++#undef module_param	/* just in case */
++#define	module_param(a,b,c)		MODULE_PARM(a,"i")
++#endif
++
++#define bzero(s,l)		memset(s,0,l)
++#define bcopy(s,d,l)	memcpy(d,s,l)
++#define bcmp(x, y, l)	memcmp(x,y,l)
++
++#define MIN(x,y)	((x) < (y) ? (x) : (y))
++
++#define device_printf(dev, a...) ({ \
++				printk("%s: ", device_get_nameunit(dev)); printk(a); \
++			})
++
++#undef printf
++#define printf(fmt...)	printk(fmt)
++
++#define KASSERT(c,p)	if (!(c)) { printk p ; } else
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++#define ocf_daemonize(str) \
++	daemonize(); \
++	spin_lock_irq(&current->sigmask_lock); \
++	sigemptyset(&current->blocked); \
++	recalc_sigpending(current); \
++	spin_unlock_irq(&current->sigmask_lock); \
++	sprintf(current->comm, str);
++#else
++#define ocf_daemonize(str) daemonize(str);
++#endif
++
++#define	TAILQ_INSERT_TAIL(q,d,m) list_add_tail(&(d)->m, (q))
++#define	TAILQ_EMPTY(q)	list_empty(q)
++#define	TAILQ_FOREACH(v, q, m) list_for_each_entry(v, q, m)
++
++#define read_random(p,l) get_random_bytes(p,l)
++
++#define DELAY(x)	((x) > 2000 ? mdelay((x)/1000) : udelay(x))
++#define strtoul simple_strtoul
++
++#define pci_get_vendor(dev)	((dev)->vendor)
++#define pci_get_device(dev)	((dev)->device)
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++#define pci_set_consistent_dma_mask(dev, mask) (0)
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
++#define pci_dma_sync_single_for_cpu pci_dma_sync_single
++#endif
++
++#ifndef DMA_32BIT_MASK
++#define DMA_32BIT_MASK  0x00000000ffffffffULL
++#endif
++
++#define htole32(x)	cpu_to_le32(x)
++#define htobe32(x)	cpu_to_be32(x)
++#define htole16(x)	cpu_to_le16(x)
++#define htobe16(x)	cpu_to_be16(x)
++
++/* older kernels don't have these */
++
++#ifndef IRQ_NONE
++#define IRQ_NONE
++#define IRQ_HANDLED
++#define irqreturn_t void
++#endif
++#ifndef IRQF_SHARED
++#define IRQF_SHARED	SA_SHIRQ
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++# define strlcpy(dest,src,len) \
++		({strncpy(dest,src,(len)-1); ((char *)dest)[(len)-1] = '\0'; })
++#endif
++
++#ifndef MAX_ERRNO
++#define MAX_ERRNO	4095
++#endif
++#ifndef IS_ERR_VALUE
++#define IS_ERR_VALUE(x) ((unsigned long)(x) >= (unsigned long)-MAX_ERRNO)
++#endif
++
++/*
++ * common debug for all
++ */
++#if 1
++#define dprintk(a...)	do { if (debug) printk(a); } while(0)
++#else
++#define dprintk(a...)
++#endif
++
++#ifndef SLAB_ATOMIC
++/* Changed in 2.6.20, must use GFP_ATOMIC now */
++#define	SLAB_ATOMIC	GFP_ATOMIC
++#endif
++
++/*
++ * need some additional support for older kernels */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,2)
++#define pci_register_driver_compat(driver, rc) \
++	do { \
++		if ((rc) > 0) { \
++			(rc) = 0; \
++		} else if (rc == 0) { \
++			(rc) = -ENODEV; \
++		} else { \
++			pci_unregister_driver(driver); \
++		} \
++	} while (0)
++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
++#define pci_register_driver_compat(driver,rc) ((rc) = (rc) < 0 ? (rc) : 0)
++#else
++#define pci_register_driver_compat(driver,rc)
++#endif
++
++#endif /* __KERNEL__ */
++
++/****************************************************************************/
++#endif /* _BSD_COMPAT_H_ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/ocfnull/Makefile linux-2.6.23.16/crypto/ocf/ocfnull/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/ocfnull/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/ocfnull/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,12 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_OCFNULL) += ocfnull.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/..
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/ocfnull/ocfnull.c linux-2.6.23.16/crypto/ocf/ocfnull/ocfnull.c
+--- linux-2.6.23.16.old/crypto/ocf/ocfnull/ocfnull.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/ocfnull/ocfnull.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,203 @@
++/*
++ * An OCF module for determining the cost of crypto versus the cost of
++ * IPSec processing outside of OCF.  This modules gives us the effect of
++ * zero cost encryption,  of course you will need to run it at both ends
++ * since it does no crypto at all.
++ *
++ * Written by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough 
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this product
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/crypto.h>
++#include <linux/interrupt.h>
++
++#include <cryptodev.h>
++#include <uio.h>
++
++static int32_t			 null_id = -1;
++static u_int32_t		 null_sesnum = 0;
++
++static int null_process(device_t, struct cryptop *, int);
++static int null_newsession(device_t, u_int32_t *, struct cryptoini *);
++static int null_freesession(device_t, u_int64_t);
++
++#define debug ocfnull_debug
++int ocfnull_debug = 0;
++module_param(ocfnull_debug, int, 0644);
++MODULE_PARM_DESC(ocfnull_debug, "Enable debug");
++
++/*
++ * dummy device structure
++ */
++
++static struct {
++	softc_device_decl	sc_dev;
++} nulldev;
++
++static device_method_t null_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	null_newsession),
++	DEVMETHOD(cryptodev_freesession,null_freesession),
++	DEVMETHOD(cryptodev_process,	null_process),
++};
++
++/*
++ * Generate a new software session.
++ */
++static int
++null_newsession(device_t arg, u_int32_t *sid, struct cryptoini *cri)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid == NULL || cri == NULL) {
++		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	if (null_sesnum == 0)
++		null_sesnum++;
++	*sid = null_sesnum++;
++	return 0;
++}
++
++
++/*
++ * Free a session.
++ */
++static int
++null_freesession(device_t arg, u_int64_t tid)
++{
++	u_int32_t sid = CRYPTO_SESID2LID(tid);
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid > null_sesnum) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	/* Silently accept and return */
++	if (sid == 0)
++		return 0;
++	return 0;
++}
++
++
++/*
++ * Process a request.
++ */
++static int
++null_process(device_t arg, struct cryptop *crp, int hint)
++{
++	unsigned int lid;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	/* Sanity check */
++	if (crp == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	crp->crp_etype = 0;
++
++	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		crp->crp_etype = EINVAL;
++		goto done;
++	}
++
++	/*
++	 * find the session we are using
++	 */
++
++	lid = crp->crp_sid & 0xffffffff;
++	if (lid >= null_sesnum || lid == 0) {
++		crp->crp_etype = ENOENT;
++		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
++		goto done;
++	}
++
++done:
++	crypto_done(crp);
++	return 0;
++}
++
++
++/*
++ * our driver startup and shutdown routines
++ */
++
++static int
++null_init(void)
++{
++	dprintk("%s(%p)\n", __FUNCTION__, null_init);
++
++	memset(&nulldev, 0, sizeof(nulldev));
++	softc_device_init(&nulldev, "ocfnull", 0, null_methods);
++
++	null_id = crypto_get_driverid(softc_get_device(&nulldev),
++				CRYPTOCAP_F_HARDWARE);
++	if (null_id < 0)
++		panic("ocfnull: crypto device cannot initialize!");
++
++#define	REGISTER(alg) \
++	crypto_register(null_id,alg,0,0)
++	REGISTER(CRYPTO_DES_CBC);
++	REGISTER(CRYPTO_3DES_CBC);
++	REGISTER(CRYPTO_RIJNDAEL128_CBC);
++	REGISTER(CRYPTO_MD5);
++	REGISTER(CRYPTO_SHA1);
++	REGISTER(CRYPTO_MD5_HMAC);
++	REGISTER(CRYPTO_SHA1_HMAC);
++#undef REGISTER
++
++	return 0;
++}
++
++static void
++null_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	crypto_unregister_all(null_id);
++	null_id = -1;
++}
++
++module_init(null_init);
++module_exit(null_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("ocfnull - claims a lot but does nothing");
+diff -urN linux-2.6.23.16.old/crypto/ocf/pasemi/Makefile linux-2.6.23.16/crypto/ocf/pasemi/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/pasemi/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/pasemi/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,12 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_PASEMI) += pasemi.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/pasemi/pasemi.c linux-2.6.23.16/crypto/ocf/pasemi/pasemi.c
+--- linux-2.6.23.16.old/crypto/ocf/pasemi/pasemi.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/pasemi/pasemi.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,1009 @@
++/*
++ * Copyright (C) 2007 PA Semi, Inc
++ *
++ * Driver for the PA Semi PWRficient DMA Crypto Engine
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/random.h>
++#include <linux/skbuff.h>
++#include <asm/scatterlist.h>
++#include <linux/moduleparam.h>
++#include <linux/pci.h>
++#include <cryptodev.h>
++#include <uio.h>
++#include "pasemi_fnu.h"
++
++#define DRV_NAME "pasemi"
++
++#define TIMER_INTERVAL 1000
++
++static void __devexit pasemi_dma_remove(struct pci_dev *pdev);
++static struct pasdma_status volatile * dma_status;
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable debug");
++
++static void pasemi_desc_start(struct pasemi_desc *desc, u64 hdr)
++{
++	desc->postop = 0;
++	desc->quad[0] = hdr;
++	desc->quad_cnt = 1;
++	desc->size = 1;
++}
++
++static void pasemi_desc_build(struct pasemi_desc *desc, u64 val)
++{
++	desc->quad[desc->quad_cnt++] = val;
++	desc->size = (desc->quad_cnt + 1) / 2;
++}
++
++static void pasemi_desc_hdr(struct pasemi_desc *desc, u64 hdr)
++{
++	desc->quad[0] |= hdr;
++}
++
++static int pasemi_desc_size(struct pasemi_desc *desc)
++{
++	return desc->size;
++}
++
++static void pasemi_ring_add_desc(
++				 struct pasemi_fnu_txring *ring,
++				 struct pasemi_desc *desc,
++				 struct cryptop *crp) {
++	int i;
++	int ring_index = 2 * (ring->next_to_fill & (TX_RING_SIZE-1));
++
++	TX_DESC_INFO(ring, ring->next_to_fill).desc_size = desc->size;
++	TX_DESC_INFO(ring, ring->next_to_fill).desc_postop = desc->postop;
++	TX_DESC_INFO(ring, ring->next_to_fill).cf_crp = crp;
++
++	for (i = 0; i < desc->quad_cnt; i += 2) {
++		ring_index = 2 * (ring->next_to_fill & (TX_RING_SIZE-1));
++		ring->desc[ring_index] = desc->quad[i];
++		ring->desc[ring_index + 1] = desc->quad[i + 1];
++		ring->next_to_fill++;
++	}
++
++	if (desc->quad_cnt & 1)
++		ring->desc[ring_index + 1] = 0;
++}
++
++static void pasemi_ring_incr(struct pasemi_softc *sc, int chan_index, int incr)
++{
++	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_INCR(sc->base_chan + chan_index),
++		 incr);
++}
++
++/*
++ * Generate a new software session.
++ */
++static int
++pasemi_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
++{
++	struct cryptoini *c, *encini = NULL, *macini = NULL;
++	struct pasemi_softc *sc = device_get_softc(dev);
++	struct pasemi_session *ses = NULL, **sespp;
++	int sesn, blksz = 0;
++	u64 ccmd = 0;
++	unsigned long flags;
++	struct pasemi_desc init_desc;
++	struct pasemi_fnu_txring *txring;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++	if (sidp == NULL || cri == NULL || sc == NULL) {
++		DPRINTF("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return -EINVAL;
++	}
++	for (c = cri; c != NULL; c = c->cri_next) {
++		if (ALG_IS_SIG(c->cri_alg)) {
++			if (macini)
++				return -EINVAL;
++			macini = c;
++		} else if (ALG_IS_CIPHER(c->cri_alg)) {
++			if (encini)
++				return -EINVAL;
++			encini = c;
++		} else {
++			DPRINTF("UNKNOWN c->cri_alg %d\n", c->cri_alg);
++			return -EINVAL;
++		}
++	}
++	if (encini == NULL && macini == NULL)
++		return -EINVAL;
++	if (encini) {
++		/* validate key length */
++		switch (encini->cri_alg) {
++		case CRYPTO_DES_CBC:
++			if (encini->cri_klen != 64)
++				return -EINVAL;
++			ccmd = DMA_CALGO_DES;
++			break;
++		case CRYPTO_3DES_CBC:
++			if (encini->cri_klen != 192)
++				return -EINVAL;
++			ccmd = DMA_CALGO_3DES;
++			break;
++		case CRYPTO_AES_CBC:
++			if (encini->cri_klen != 128 &&
++			    encini->cri_klen != 192 &&
++			    encini->cri_klen != 256)
++				return -EINVAL;
++			ccmd = DMA_CALGO_AES;
++			break;
++		case CRYPTO_ARC4:
++			if (encini->cri_klen != 128)
++				return -EINVAL;
++			ccmd = DMA_CALGO_ARC;
++			break;
++		default:
++			DPRINTF("UNKNOWN encini->cri_alg %d\n",
++				encini->cri_alg);
++			return -EINVAL;
++		}
++	}
++
++	if (macini) {
++		switch (macini->cri_alg) {
++		case CRYPTO_MD5:
++		case CRYPTO_MD5_HMAC:
++			blksz = 16;
++			break;
++		case CRYPTO_SHA1:
++		case CRYPTO_SHA1_HMAC:
++			blksz = 20;
++			break;
++		default:
++			DPRINTF("UNKNOWN macini->cri_alg %d\n",
++				macini->cri_alg);
++			return -EINVAL;
++		}
++		if (((macini->cri_klen + 7) / 8) > blksz) {
++			DPRINTF("key length %d bigger than blksize %d not supported\n",
++				((macini->cri_klen + 7) / 8), blksz);
++			return -EINVAL;
++		}
++	}
++
++	for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
++		if (sc->sc_sessions[sesn] == NULL) {
++			sc->sc_sessions[sesn] = (struct pasemi_session *)
++				kzalloc(sizeof(struct pasemi_session), GFP_ATOMIC);
++			ses = sc->sc_sessions[sesn];
++			break;
++		} else if (sc->sc_sessions[sesn]->used == 0) {
++			ses = sc->sc_sessions[sesn];
++			break;
++		}
++	}
++
++	if (ses == NULL) {
++		sespp = (struct pasemi_session **)
++			kzalloc(sc->sc_nsessions * 2 *
++				sizeof(struct pasemi_session *), GFP_ATOMIC);
++		if (sespp == NULL)
++			return -ENOMEM;
++		memcpy(sespp, sc->sc_sessions,
++		       sc->sc_nsessions * sizeof(struct pasemi_session *));
++		kfree(sc->sc_sessions);
++		sc->sc_sessions = sespp;
++		sesn = sc->sc_nsessions;
++		ses = sc->sc_sessions[sesn] = (struct pasemi_session *)
++			kzalloc(sizeof(struct pasemi_session), GFP_ATOMIC);
++		if (ses == NULL)
++			return -ENOMEM;
++		sc->sc_nsessions *= 2;
++	}
++
++	ses->used = 1;
++
++	ses->dma_addr = pci_map_single(sc->dma_pdev, (void *) ses->civ,
++				       sizeof(struct pasemi_session), DMA_TO_DEVICE);
++
++	/* enter the channel scheduler */
++	spin_lock_irqsave(&sc->sc_chnlock, flags);
++
++	/* ARC4 has to be processed by the even channel */
++	if (encini && (encini->cri_alg == CRYPTO_ARC4))
++		ses->chan = sc->sc_lastchn & ~1;
++	else
++		ses->chan = sc->sc_lastchn;
++	sc->sc_lastchn = (sc->sc_lastchn + 1) % sc->sc_num_channels;
++
++	spin_unlock_irqrestore(&sc->sc_chnlock, flags);
++
++	txring = &sc->tx[ses->chan];
++
++	if (encini) {
++		ses->ccmd = ccmd;
++
++		/* get an IV */
++		/* XXX may read fewer than requested */
++		get_random_bytes(ses->civ, sizeof(ses->civ));
++
++		ses->keysz = (encini->cri_klen - 63) / 64;
++		memcpy(ses->key, encini->cri_key, (ses->keysz + 1) * 8);
++
++		pasemi_desc_start(&init_desc,
++				  XCT_CTRL_HDR(ses->chan, (encini && macini) ? 0x68 : 0x40, DMA_FN_CIV0));
++		pasemi_desc_build(&init_desc,
++				  XCT_FUN_SRC_PTR((encini && macini) ? 0x68 : 0x40, ses->dma_addr));
++	}
++	if (macini) {
++		if (macini->cri_alg == CRYPTO_MD5_HMAC ||
++		    macini->cri_alg == CRYPTO_SHA1_HMAC)
++			memcpy(ses->hkey, macini->cri_key, blksz);
++		else {
++			/* Load initialization constants(RFC 1321, 3174) */
++			ses->hiv[0] = 0x67452301efcdab89ULL;
++			ses->hiv[1] = 0x98badcfe10325476ULL;
++			ses->hiv[2] = 0xc3d2e1f000000000ULL;
++		}
++		ses->hseq = 0ULL;
++	}
++
++	spin_lock_irqsave(&txring->fill_lock, flags);
++
++	if (((txring->next_to_fill + pasemi_desc_size(&init_desc)) -
++	     txring->next_to_clean) > TX_RING_SIZE) {
++		spin_unlock_irqrestore(&txring->fill_lock, flags);
++		return ERESTART;
++	}
++
++	if (encini) {
++		pasemi_ring_add_desc(txring, &init_desc, NULL);
++		pasemi_ring_incr(sc, ses->chan,
++				 pasemi_desc_size(&init_desc));
++	}
++
++	txring->sesn = sesn;
++	spin_unlock_irqrestore(&txring->fill_lock, flags);
++
++	*sidp = PASEMI_SID(sesn);
++	return 0;
++}
++
++/*
++ * Deallocate a session.
++ */
++static int
++pasemi_freesession(device_t dev, u_int64_t tid)
++{
++	struct pasemi_softc *sc = device_get_softc(dev);
++	int session;
++	u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (sc == NULL)
++		return -EINVAL;
++	session = PASEMI_SESSION(sid);
++	if (session >= sc->sc_nsessions || !sc->sc_sessions[session])
++		return -EINVAL;
++
++	pci_unmap_single(sc->dma_pdev,
++			 sc->sc_sessions[session]->dma_addr,
++			 sizeof(struct pasemi_session), DMA_TO_DEVICE);
++	memset(sc->sc_sessions[session], 0,
++	       sizeof(struct pasemi_session));
++
++	return 0;
++}
++
++static int
++pasemi_process(device_t dev, struct cryptop *crp, int hint)
++{
++
++	int err = 0, ivsize, srclen = 0, reinit = 0, reinit_size = 0, chsel;
++	struct pasemi_softc *sc = device_get_softc(dev);
++	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
++	caddr_t ivp;
++	struct pasemi_desc init_desc, work_desc;
++	struct pasemi_session *ses;
++	struct sk_buff *skb;
++	struct uio *uiop;
++	unsigned long flags;
++	struct pasemi_fnu_txring *txring;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (crp == NULL || crp->crp_callback == NULL || sc == NULL)
++		return -EINVAL;
++
++	crp->crp_etype = 0;
++	if (PASEMI_SESSION(crp->crp_sid) >= sc->sc_nsessions)
++		return -EINVAL;
++
++	ses = sc->sc_sessions[PASEMI_SESSION(crp->crp_sid)];
++
++	crd1 = crp->crp_desc;
++	if (crd1 == NULL) {
++		err = -EINVAL;
++		goto errout;
++	}
++	crd2 = crd1->crd_next;
++
++	if (ALG_IS_SIG(crd1->crd_alg)) {
++		maccrd = crd1;
++		if (crd2 == NULL)
++			enccrd = NULL;
++		else if (ALG_IS_CIPHER(crd2->crd_alg) &&
++			 (crd2->crd_flags & CRD_F_ENCRYPT) == 0)
++			enccrd = crd2;
++		else
++			goto erralg;
++	} else if (ALG_IS_CIPHER(crd1->crd_alg)) {
++		enccrd = crd1;
++		if (crd2 == NULL)
++			maccrd = NULL;
++		else if (ALG_IS_SIG(crd2->crd_alg) &&
++			 (crd1->crd_flags & CRD_F_ENCRYPT))
++			maccrd = crd2;
++		else
++			goto erralg;
++	} else
++		goto erralg;
++
++	chsel = ses->chan;
++
++	txring = &sc->tx[chsel];
++
++	if (enccrd && !maccrd) {
++		if (enccrd->crd_alg == CRYPTO_ARC4)
++			reinit = 1;
++		reinit_size = 0x40;
++		srclen = crp->crp_ilen;
++
++		pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I
++				  | XCT_FUN_FUN(chsel));
++		if (enccrd->crd_flags & CRD_F_ENCRYPT)
++			pasemi_desc_hdr(&work_desc, XCT_FUN_CRM_ENC);
++		else
++			pasemi_desc_hdr(&work_desc, XCT_FUN_CRM_DEC);
++	} else if (enccrd && maccrd) {
++		if (enccrd->crd_alg == CRYPTO_ARC4)
++			reinit = 1;
++		reinit_size = 0x68;
++
++		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
++			/* Encrypt -> Authenticate */
++			pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_ENC_SIG
++					  | XCT_FUN_A | XCT_FUN_FUN(chsel));
++			srclen = maccrd->crd_skip + maccrd->crd_len;
++		} else {
++			/* Authenticate -> Decrypt */
++			pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_SIG_DEC
++					  | XCT_FUN_24BRES | XCT_FUN_FUN(chsel));
++			pasemi_desc_build(&work_desc, 0);
++			pasemi_desc_build(&work_desc, 0);
++			pasemi_desc_build(&work_desc, 0);
++			work_desc.postop = PASEMI_CHECK_SIG;
++			srclen = crp->crp_ilen;
++		}
++
++		pasemi_desc_hdr(&work_desc, XCT_FUN_SHL(maccrd->crd_skip / 4));
++		pasemi_desc_hdr(&work_desc, XCT_FUN_CHL(enccrd->crd_skip - maccrd->crd_skip));
++	} else if (!enccrd && maccrd) {
++		srclen = maccrd->crd_len;
++
++		pasemi_desc_start(&init_desc,
++				  XCT_CTRL_HDR(chsel, 0x58, DMA_FN_HKEY0));
++		pasemi_desc_build(&init_desc,
++				  XCT_FUN_SRC_PTR(0x58, ((struct pasemi_session *)ses->dma_addr)->hkey));
++
++		pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_SIG
++				  | XCT_FUN_A | XCT_FUN_FUN(chsel));
++	}
++
++	if (enccrd) {
++		switch (enccrd->crd_alg) {
++		case CRYPTO_3DES_CBC:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_3DES |
++					XCT_FUN_BCM_CBC);
++			ivsize = sizeof(u64);
++			break;
++		case CRYPTO_DES_CBC:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_DES |
++					XCT_FUN_BCM_CBC);
++			ivsize = sizeof(u64);
++			break;
++		case CRYPTO_AES_CBC:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_AES |
++					XCT_FUN_BCM_CBC);
++			ivsize = 2 * sizeof(u64);
++			break;
++		case CRYPTO_ARC4:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_ARC);
++			ivsize = 0;
++			break;
++		default:
++			printk(DRV_NAME ": unimplemented enccrd->crd_alg %d\n",
++			       enccrd->crd_alg);
++			err = -EINVAL;
++			goto errout;
++		}
++
++		ivp = (ivsize == sizeof(u64)) ? (caddr_t) &ses->civ[1] : (caddr_t) &ses->civ[0];
++		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
++			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
++				memcpy(ivp, enccrd->crd_iv, ivsize);
++			/* If IV is not present in the buffer already, it has to be copied there */
++			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
++				crypto_copyback(crp->crp_flags, crp->crp_buf,
++						enccrd->crd_inject, ivsize, ivp);
++		} else {
++			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
++				/* IV is provided expicitly in descriptor */
++				memcpy(ivp, enccrd->crd_iv, ivsize);
++			else
++				/* IV is provided in the packet */
++				crypto_copydata(crp->crp_flags, crp->crp_buf,
++						enccrd->crd_inject, ivsize,
++						ivp);
++		}
++	}
++
++	if (maccrd) {
++		switch (maccrd->crd_alg) {
++		case CRYPTO_MD5:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_MD5 |
++					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
++			break;
++		case CRYPTO_SHA1:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_SHA1 |
++					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
++			break;
++		case CRYPTO_MD5_HMAC:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_HMAC_MD5 |
++					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
++			break;
++		case CRYPTO_SHA1_HMAC:
++			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_HMAC_SHA1 |
++					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
++			break;
++		default:
++			printk(DRV_NAME ": unimplemented maccrd->crd_alg %d\n",
++			       maccrd->crd_alg);
++			err = -EINVAL;
++			goto errout;
++		}
++	}
++
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		/* using SKB buffers */
++		skb = (struct sk_buff *)crp->crp_buf;
++		if (skb_shinfo(skb)->nr_frags) {
++			printk(DRV_NAME ": skb frags unimplemented\n");
++			err = -EINVAL;
++			goto errout;
++		}
++		pasemi_desc_build(
++			&work_desc,
++			XCT_FUN_DST_PTR(skb->len, pci_map_single(
++						sc->dma_pdev, skb->data,
++						skb->len, DMA_TO_DEVICE)));
++		pasemi_desc_build(
++			&work_desc,
++			XCT_FUN_SRC_PTR(
++				srclen, pci_map_single(
++					sc->dma_pdev, skb->data,
++					srclen, DMA_TO_DEVICE)));
++		pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		/* using IOV buffers */
++		uiop = (struct uio *)crp->crp_buf;
++		if (uiop->uio_iovcnt > 1) {
++			printk(DRV_NAME ": iov frags unimplemented\n");
++			err = -EINVAL;
++			goto errout;
++		}
++
++		/* crp_olen is never set; always use crp_ilen */
++		pasemi_desc_build(
++			&work_desc,
++			XCT_FUN_DST_PTR(crp->crp_ilen, pci_map_single(
++						sc->dma_pdev,
++						uiop->uio_iov->iov_base,
++						crp->crp_ilen, DMA_TO_DEVICE)));
++		pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
++
++		pasemi_desc_build(
++			&work_desc,
++			XCT_FUN_SRC_PTR(srclen, pci_map_single(
++						sc->dma_pdev,
++						uiop->uio_iov->iov_base,
++						srclen, DMA_TO_DEVICE)));
++	} else {
++		/* using contig buffers */
++		pasemi_desc_build(
++			&work_desc,
++			XCT_FUN_DST_PTR(crp->crp_ilen, pci_map_single(
++						sc->dma_pdev,
++						crp->crp_buf,
++						crp->crp_ilen, DMA_TO_DEVICE)));
++		pasemi_desc_build(
++			&work_desc,
++			XCT_FUN_SRC_PTR(srclen, pci_map_single(
++						sc->dma_pdev,
++						crp->crp_buf, srclen,
++						DMA_TO_DEVICE)));
++		pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
++	}
++
++	spin_lock_irqsave(&txring->fill_lock, flags);
++
++	if (txring->sesn != PASEMI_SESSION(crp->crp_sid)) {
++		txring->sesn = PASEMI_SESSION(crp->crp_sid);
++		reinit = 1;
++	}
++
++	if (enccrd) {
++		pasemi_desc_start(&init_desc,
++				  XCT_CTRL_HDR(chsel, reinit ? reinit_size : 0x10, DMA_FN_CIV0));
++		pasemi_desc_build(&init_desc,
++				  XCT_FUN_SRC_PTR(reinit ? reinit_size : 0x10, ses->dma_addr));
++	}
++
++	if (((txring->next_to_fill + pasemi_desc_size(&init_desc) +
++	      pasemi_desc_size(&work_desc)) -
++	     txring->next_to_clean) > TX_RING_SIZE) {
++		spin_unlock_irqrestore(&txring->fill_lock, flags);
++		err = ERESTART;
++		goto errout;
++	}
++
++	pasemi_ring_add_desc(txring, &init_desc, NULL);
++	pasemi_ring_add_desc(txring, &work_desc, crp);
++
++	pasemi_ring_incr(sc, chsel,
++			 pasemi_desc_size(&init_desc) +
++			 pasemi_desc_size(&work_desc));
++
++	spin_unlock_irqrestore(&txring->fill_lock, flags);
++
++	mod_timer(&txring->crypto_timer, jiffies + TIMER_INTERVAL);
++
++	return 0;
++
++erralg:
++	printk(DRV_NAME ": unsupported algorithm or algorithm order alg1 %d alg2 %d\n",
++	       crd1->crd_alg, crd2->crd_alg);
++	err = -EINVAL;
++
++errout:
++	if (err != ERESTART) {
++		crp->crp_etype = err;
++		crypto_done(crp);
++	}
++	return err;
++}
++
++static int pasemi_clean_tx(struct pasemi_softc *sc, int chan)
++{
++	int i, j, ring_idx;
++	struct pasemi_fnu_txring *ring = &sc->tx[chan];
++	u16 delta_cnt;
++	int flags, loops = 10;
++	int desc_size;
++	struct cryptop *crp;
++
++	spin_lock_irqsave(&ring->clean_lock, flags);
++
++	while ((delta_cnt = (dma_status->tx_sta[sc->base_chan + chan]
++			     & PAS_STATUS_PCNT_M) - ring->total_pktcnt)
++	       && loops--) {
++
++		for (i = 0; i < delta_cnt; i++) {
++			desc_size = TX_DESC_INFO(ring, ring->next_to_clean).desc_size;
++			crp = TX_DESC_INFO(ring, ring->next_to_clean).cf_crp;
++			if (crp) {
++				ring_idx = 2 * (ring->next_to_clean & (TX_RING_SIZE-1));
++				if (TX_DESC_INFO(ring, ring->next_to_clean).desc_postop & PASEMI_CHECK_SIG) {
++					/* Need to make sure signature matched,
++					 * if not - return error */
++					if (!(ring->desc[ring_idx + 1] & (1ULL << 63)))
++						crp->crp_etype = -EINVAL;
++				}
++				crypto_done(TX_DESC_INFO(ring,
++							 ring->next_to_clean).cf_crp);
++				TX_DESC_INFO(ring, ring->next_to_clean).cf_crp = NULL;
++				pci_unmap_single(
++					sc->dma_pdev,
++					XCT_PTR_ADDR_LEN(ring->desc[ring_idx + 1]),
++					PCI_DMA_TODEVICE);
++
++				ring->desc[ring_idx] = ring->desc[ring_idx + 1] = 0;
++
++				ring->next_to_clean++;
++				for (j = 1; j < desc_size; j++) {
++					ring_idx = 2 *
++						(ring->next_to_clean &
++						 (TX_RING_SIZE-1));
++					pci_unmap_single(
++						sc->dma_pdev,
++						XCT_PTR_ADDR_LEN(ring->desc[ring_idx]),
++						PCI_DMA_TODEVICE);
++					if (ring->desc[ring_idx + 1])
++						pci_unmap_single(
++							sc->dma_pdev,
++							XCT_PTR_ADDR_LEN(
++								ring->desc[
++									ring_idx + 1]),
++							PCI_DMA_TODEVICE);
++					ring->desc[ring_idx] =
++						ring->desc[ring_idx + 1] = 0;
++					ring->next_to_clean++;
++				}
++			} else {
++				for (j = 0; j < desc_size; j++) {
++					ring_idx = 2 * (ring->next_to_clean & (TX_RING_SIZE-1));
++					ring->desc[ring_idx] =
++						ring->desc[ring_idx + 1] = 0;
++					ring->next_to_clean++;
++				}
++			}
++		}
++
++		ring->total_pktcnt += delta_cnt;
++	}
++	spin_unlock_irqrestore(&ring->clean_lock, flags);
++
++	return 0;
++}
++
++static void sweepup_tx(struct pasemi_softc *sc)
++{
++	int i;
++
++	for (i = 0; i < sc->sc_num_channels; i++)
++		pasemi_clean_tx(sc, i);
++}
++
++static irqreturn_t pasemi_intr(int irq, void *arg, struct pt_regs *regs)
++{
++	struct pasemi_softc *sc = arg;
++	unsigned int reg;
++	int chan = irq - sc->base_irq;
++	int chan_index = sc->base_chan + chan;
++	u64 stat = dma_status->tx_sta[chan_index];
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (!(stat & PAS_STATUS_CAUSE_M))
++		return IRQ_NONE;
++
++	pasemi_clean_tx(sc, chan);
++
++	stat = dma_status->tx_sta[chan_index];
++
++	reg = PAS_IOB_DMA_TXCH_RESET_PINTC |
++		PAS_IOB_DMA_TXCH_RESET_PCNT(sc->tx[chan].total_pktcnt);
++
++	if (stat & PAS_STATUS_SOFT)
++		reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
++
++	out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_RESET(chan_index), reg);
++
++
++	return IRQ_HANDLED;
++}
++
++static int pasemi_dma_setup_tx_resources(struct pasemi_softc *sc, int chan)
++{
++	u32 val;
++	int chan_index = chan + sc->base_chan;
++	int ret;
++	struct pasemi_fnu_txring *ring;
++
++	ring = &sc->tx[chan];
++
++	spin_lock_init(&ring->fill_lock);
++	spin_lock_init(&ring->clean_lock);
++
++	ring->desc_info = kzalloc(sizeof(struct pasemi_desc_info) *
++				  TX_RING_SIZE, GFP_KERNEL);
++	if (!ring->desc_info)
++		return -ENOMEM;
++
++	/* Allocate descriptors */
++	ring->desc = dma_alloc_coherent(&sc->dma_pdev->dev,
++					TX_RING_SIZE *
++					2 * sizeof(u64),
++					&ring->dma, GFP_KERNEL);
++	if (!ring->desc)
++		return -ENOMEM;
++
++	memset((void *) ring->desc, 0, TX_RING_SIZE * 2 * sizeof(u64));
++
++	out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_RESET(chan_index), 0x30);
++
++	ring->total_pktcnt = 0;
++
++	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_BASEL(chan_index),
++		 PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
++
++	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
++	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2);
++
++	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_BASEU(chan_index), val);
++
++	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_CFG(chan_index),
++		 PAS_DMA_TXCHAN_CFG_TY_FUNC |
++		 PAS_DMA_TXCHAN_CFG_TATTR(chan) |
++		 PAS_DMA_TXCHAN_CFG_WT(2));
++
++	/* enable tx channel */
++	out_le32(sc->dma_regs +
++		 PAS_DMA_TXCHAN_TCMDSTA(chan_index),
++		 PAS_DMA_TXCHAN_TCMDSTA_EN);
++
++	out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_CFG(chan_index),
++		 PAS_IOB_DMA_TXCH_CFG_CNTTH(1000));
++
++	ring->next_to_fill = 0;
++	ring->next_to_clean = 0;
++
++	snprintf(ring->irq_name, sizeof(ring->irq_name),
++		 "%s%d", "crypto", chan);
++
++	ring->irq = irq_create_mapping(NULL, sc->base_irq + chan);
++	ret = request_irq(ring->irq, (irq_handler_t)
++			  pasemi_intr, IRQF_DISABLED, ring->irq_name, sc);
++	if (ret) {
++		printk(KERN_ERR DRV_NAME ": failed to hook irq %d ret %d\n",
++		       ring->irq, ret);
++		ring->irq = -1;
++		return ret;
++	}
++
++	setup_timer(&ring->crypto_timer, (void *) sweepup_tx, (unsigned long) sc);
++
++	return 0;
++}
++
++static device_method_t pasemi_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,		pasemi_newsession),
++	DEVMETHOD(cryptodev_freesession,	pasemi_freesession),
++	DEVMETHOD(cryptodev_process,		pasemi_process),
++};
++
++/* Set up the crypto device structure, private data,
++ * and anything else we need before we start */
++
++static int __devinit
++pasemi_dma_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
++{
++	struct pasemi_softc *sc;
++	int ret, i;
++
++	DPRINTF(KERN_ERR "%s()\n", __FUNCTION__);
++
++	sc = kzalloc(sizeof(*sc), GFP_KERNEL);
++	if (!sc)
++		return -ENOMEM;
++
++	softc_device_init(sc, DRV_NAME, 1, pasemi_methods);
++
++	pci_set_drvdata(pdev, sc);
++
++	spin_lock_init(&sc->sc_chnlock);
++
++	sc->sc_sessions = (struct pasemi_session **)
++		kzalloc(PASEMI_INITIAL_SESSIONS *
++			sizeof(struct pasemi_session *), GFP_ATOMIC);
++	if (sc->sc_sessions == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	sc->sc_nsessions = PASEMI_INITIAL_SESSIONS;
++	sc->sc_lastchn = 0;
++	sc->base_irq = pdev->irq + 6;
++	sc->base_chan = 6;
++	sc->sc_cid = -1;
++	sc->dma_pdev = pdev;
++
++	sc->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
++	if (!sc->iob_pdev) {
++		dev_err(&pdev->dev, "Can't find I/O Bridge\n");
++		ret = -ENODEV;
++		goto out;
++	}
++
++	/* This is hardcoded and ugly, but we have some firmware versions
++	 * who don't provide the register space in the device tree. Luckily
++	 * they are at well-known locations so we can just do the math here.
++	 */
++	sc->dma_regs =
++		ioremap(0xe0000000 + (sc->dma_pdev->devfn << 12), 0x2000);
++	sc->iob_regs =
++		ioremap(0xe0000000 + (sc->iob_pdev->devfn << 12), 0x2000);
++	if (!sc->dma_regs || !sc->iob_regs) {
++		dev_err(&pdev->dev, "Can't map registers\n");
++		ret = -ENODEV;
++		goto out;
++	}
++
++	dma_status = __ioremap(0xfd800000, 0x1000, 0);
++	if (!dma_status) {
++		ret = -ENODEV;
++		dev_err(&pdev->dev, "Can't map dmastatus space\n");
++		goto out;
++	}
++
++	sc->tx = (struct pasemi_fnu_txring *)
++		kzalloc(sizeof(struct pasemi_fnu_txring)
++			* 8, GFP_KERNEL);
++	if (!sc->tx) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	/* Initialize the h/w */
++	out_le32(sc->dma_regs + PAS_DMA_COM_CFG,
++		 (in_le32(sc->dma_regs + PAS_DMA_COM_CFG) |
++		  PAS_DMA_COM_CFG_FWF));
++	out_le32(sc->dma_regs + PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
++
++	for (i = 0; i < PASEMI_FNU_CHANNELS; i++) {
++		sc->sc_num_channels++;
++		ret = pasemi_dma_setup_tx_resources(sc, i);
++		if (ret)
++			goto out;
++	}
++
++	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),
++					 CRYPTOCAP_F_HARDWARE);
++	if (sc->sc_cid < 0) {
++		printk(KERN_ERR DRV_NAME ": could not get crypto driver id\n");
++		ret = -ENXIO;
++		goto out;
++	}
++
++	/* register algorithms with the framework */
++	printk(DRV_NAME ":");
++
++	crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
++
++	return 0;
++
++out:
++	pasemi_dma_remove(pdev);
++	return ret;
++}
++
++#define MAX_RETRIES 5000
++
++static void pasemi_free_tx_resources(struct pasemi_softc *sc, int chan)
++{
++	struct pasemi_fnu_txring *ring = &sc->tx[chan];
++	int chan_index = chan + sc->base_chan;
++	int retries;
++	u32 stat;
++
++	/* Stop the channel */
++	out_le32(sc->dma_regs +
++		 PAS_DMA_TXCHAN_TCMDSTA(chan_index),
++		 PAS_DMA_TXCHAN_TCMDSTA_ST);
++
++	for (retries = 0; retries < MAX_RETRIES; retries++) {
++		stat = in_le32(sc->dma_regs +
++			       PAS_DMA_TXCHAN_TCMDSTA(chan_index));
++		if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
++			break;
++		cond_resched();
++	}
++
++	if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
++		dev_err(&sc->dma_pdev->dev, "Failed to stop tx channel %d\n",
++			chan_index);
++
++	/* Disable the channel */
++	out_le32(sc->dma_regs +
++		 PAS_DMA_TXCHAN_TCMDSTA(chan_index),
++		 0);
++
++	if (ring->desc_info)
++		kfree((void *) ring->desc_info);
++	if (ring->desc)
++		dma_free_coherent(&sc->dma_pdev->dev,
++				  TX_RING_SIZE *
++				  2 * sizeof(u64),
++				  (void *) ring->desc, ring->dma);
++	if (ring->irq != -1)
++		free_irq(ring->irq, sc);
++
++	del_timer(&ring->crypto_timer);
++}
++
++static void __devexit pasemi_dma_remove(struct pci_dev *pdev)
++{
++	struct pasemi_softc *sc = pci_get_drvdata(pdev);
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (sc->sc_cid >= 0) {
++		crypto_unregister_all(sc->sc_cid);
++	}
++
++	if (sc->tx) {
++		for (i = 0; i < sc->sc_num_channels; i++)
++			pasemi_free_tx_resources(sc, i);
++
++		kfree(sc->tx);
++	}
++	if (sc->sc_sessions) {
++		for (i = 0; i < sc->sc_nsessions; i++)
++			kfree(sc->sc_sessions[i]);
++		kfree(sc->sc_sessions);
++	}
++	if (sc->iob_pdev)
++		pci_dev_put(sc->iob_pdev);
++	if (sc->dma_regs)
++		iounmap(sc->dma_regs);
++	if (sc->iob_regs)
++		iounmap(sc->iob_regs);
++	kfree(sc);
++}
++
++static struct pci_device_id pasemi_dma_pci_tbl[] = {
++	{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa007) },
++};
++
++MODULE_DEVICE_TABLE(pci, pasemi_dma_pci_tbl);
++
++static struct pci_driver pasemi_dma_driver = {
++	.name		= "pasemi_dma",
++	.id_table	= pasemi_dma_pci_tbl,
++	.probe		= pasemi_dma_probe,
++	.remove		= __devexit_p(pasemi_dma_remove),
++};
++
++static void __exit pasemi_dma_cleanup_module(void)
++{
++	pci_unregister_driver(&pasemi_dma_driver);
++	__iounmap(dma_status);
++	dma_status = NULL;
++}
++
++int pasemi_dma_init_module(void)
++{
++	return pci_register_driver(&pasemi_dma_driver);
++}
++
++module_init(pasemi_dma_init_module);
++module_exit(pasemi_dma_cleanup_module);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("Egor Martovetsky egor@pasemi.com");
++MODULE_DESCRIPTION("OCF driver for PA Semi PWRficient DMA Crypto Engine");
+diff -urN linux-2.6.23.16.old/crypto/ocf/pasemi/pasemi_fnu.h linux-2.6.23.16/crypto/ocf/pasemi/pasemi_fnu.h
+--- linux-2.6.23.16.old/crypto/ocf/pasemi/pasemi_fnu.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/pasemi/pasemi_fnu.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,410 @@
++/*
++ * Copyright (C) 2007 PA Semi, Inc
++ *
++ * Driver for the PA Semi PWRficient DMA Crypto Engine, soft state and
++ * hardware register layouts.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
++ */
++
++#ifndef PASEMI_FNU_H
++#define PASEMI_FNU_H
++
++#include <linux/spinlock.h>
++
++#define	PASEMI_SESSION(sid)	((sid) & 0xffffffff)
++#define	PASEMI_SID(sesn)	((sesn) & 0xffffffff)
++#define	DPRINTF(a...)	if (debug) { printk(DRV_NAME ": " a); }
++
++/* Must be a power of two */
++#define RX_RING_SIZE 512
++#define TX_RING_SIZE 512
++#define TX_DESC(ring, num)	((ring)->desc[2 * (num & (TX_RING_SIZE-1))])
++#define TX_DESC_INFO(ring, num)	((ring)->desc_info[(num) & (TX_RING_SIZE-1)])
++#define MAX_DESC_SIZE 8
++#define PASEMI_INITIAL_SESSIONS 10
++#define PASEMI_FNU_CHANNELS 8
++
++/* DMA descriptor */
++struct pasemi_desc {
++	u64 quad[2*MAX_DESC_SIZE];
++	int quad_cnt;
++	int size;
++	int postop;
++};
++
++/*
++ * Holds per descriptor data
++ */
++struct pasemi_desc_info {
++	int			desc_size;
++	int			desc_postop;
++#define PASEMI_CHECK_SIG 0x1
++
++	struct cryptop          *cf_crp;
++};
++
++/*
++ * Holds per channel data
++ */
++struct pasemi_fnu_txring {
++	volatile u64		*desc;
++	volatile struct
++	pasemi_desc_info	*desc_info;
++	dma_addr_t		dma;
++	struct timer_list       crypto_timer;
++	spinlock_t		fill_lock;
++	spinlock_t		clean_lock;
++	unsigned int		next_to_fill;
++	unsigned int		next_to_clean;
++	u16			total_pktcnt;
++	int			irq;
++	int			sesn;
++	char			irq_name[10];
++};
++
++/*
++ * Holds data specific to a single pasemi device.
++ */
++struct pasemi_softc {
++	softc_device_decl	sc_cdev;
++	struct pci_dev		*dma_pdev;	/* device backpointer */
++	struct pci_dev		*iob_pdev;	/* device backpointer */
++	void __iomem		*dma_regs;
++	void __iomem		*iob_regs;
++	int			base_irq;
++	int			base_chan;
++	int32_t			sc_cid;		/* crypto tag */
++	int			sc_nsessions;
++	struct pasemi_session	**sc_sessions;
++	int			sc_num_channels;/* number of crypto channels */
++
++	/* pointer to the array of txring datastructures, one txring per channel */
++	struct pasemi_fnu_txring *tx;
++
++	/*
++	 * mutual exclusion for the channel scheduler
++	 */
++	spinlock_t		sc_chnlock;
++	/* last channel used, for now use round-robin to allocate channels */
++	int			sc_lastchn;
++};
++
++struct pasemi_session {
++	u64 civ[2];
++	u64 keysz;
++	u64 key[4];
++	u64 ccmd;
++	u64 hkey[4];
++	u64 hseq;
++	u64 giv[2];
++	u64 hiv[4];
++
++	int used;
++	dma_addr_t	dma_addr;
++	int chan;
++};
++
++/* status register layout in IOB region, at 0xfd800000 */
++struct pasdma_status {
++	u64 rx_sta[64];
++	u64 tx_sta[20];
++};
++
++#define ALG_IS_CIPHER(alg) ((alg == CRYPTO_DES_CBC)		|| \
++				(alg == CRYPTO_3DES_CBC)	|| \
++				(alg == CRYPTO_AES_CBC)		|| \
++				(alg == CRYPTO_ARC4)		|| \
++				(alg == CRYPTO_NULL_CBC))
++
++#define ALG_IS_SIG(alg) ((alg == CRYPTO_MD5)			|| \
++				(alg == CRYPTO_MD5_HMAC)	|| \
++				(alg == CRYPTO_SHA1)		|| \
++				(alg == CRYPTO_SHA1_HMAC)	|| \
++				(alg == CRYPTO_NULL_HMAC))
++
++enum {
++	PAS_DMA_COM_TXCMD = 0x100,	/* Transmit Command Register  */
++	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
++	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
++	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
++	PAS_DMA_COM_CFG   = 0x114,	/* DMA Configuration Register */
++};
++
++/* All these registers live in the PCI configuration space for the DMA PCI
++ * device. Use the normal PCI config access functions for them.
++ */
++
++#define PAS_DMA_COM_CFG_FWF	0x18000000
++
++#define PAS_DMA_COM_TXCMD_EN	0x00000001 /* enable */
++#define PAS_DMA_COM_TXSTA_ACT	0x00000001 /* active */
++#define PAS_DMA_COM_RXCMD_EN	0x00000001 /* enable */
++#define PAS_DMA_COM_RXSTA_ACT	0x00000001 /* active */
++
++#define _PAS_DMA_TXCHAN_STRIDE	0x20    /* Size per channel		*/
++#define _PAS_DMA_TXCHAN_TCMDSTA	0x300	/* Command / Status		*/
++#define _PAS_DMA_TXCHAN_CFG	0x304	/* Configuration		*/
++#define _PAS_DMA_TXCHAN_DSCRBU	0x308	/* Descriptor BU Allocation	*/
++#define _PAS_DMA_TXCHAN_INCR	0x310	/* Descriptor increment		*/
++#define _PAS_DMA_TXCHAN_CNT	0x314	/* Descriptor count/offset	*/
++#define _PAS_DMA_TXCHAN_BASEL	0x318	/* Descriptor ring base (low)	*/
++#define _PAS_DMA_TXCHAN_BASEU	0x31c	/*			(high)	*/
++#define PAS_DMA_TXCHAN_TCMDSTA(c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE)
++#define    PAS_DMA_TXCHAN_TCMDSTA_EN	0x00000001	/* Enabled */
++#define    PAS_DMA_TXCHAN_TCMDSTA_ST	0x00000002	/* Stop interface */
++#define    PAS_DMA_TXCHAN_TCMDSTA_ACT	0x00010000	/* Active */
++#define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
++#define    PAS_DMA_TXCHAN_CFG_TY_FUNC	0x00000002	/* Type = interface */
++#define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
++#define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
++#define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
++#define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
++					 PAS_DMA_TXCHAN_CFG_TATTR_M)
++#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
++#define    PAS_DMA_TXCHAN_CFG_WT_S	6
++#define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
++					 PAS_DMA_TXCHAN_CFG_WT_M)
++#define    PAS_DMA_TXCHAN_CFG_LPSQ_FAST	0x00000400
++#define    PAS_DMA_TXCHAN_CFG_LPDQ_FAST	0x00000800
++#define    PAS_DMA_TXCHAN_CFG_CF	0x00001000	/* Clean first line */
++#define    PAS_DMA_TXCHAN_CFG_CL	0x00002000	/* Clean last line */
++#define    PAS_DMA_TXCHAN_CFG_UP	0x00004000	/* update tx descr when sent */
++#define PAS_DMA_TXCHAN_INCR(c)    (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
++#define PAS_DMA_TXCHAN_BASEL(c)   (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
++#define    PAS_DMA_TXCHAN_BASEL_BRBL_M	0xffffffc0
++#define    PAS_DMA_TXCHAN_BASEL_BRBL_S	0
++#define    PAS_DMA_TXCHAN_BASEL_BRBL(x)	(((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \
++					 PAS_DMA_TXCHAN_BASEL_BRBL_M)
++#define PAS_DMA_TXCHAN_BASEU(c)   (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE)
++#define    PAS_DMA_TXCHAN_BASEU_BRBH_M	0x00000fff
++#define    PAS_DMA_TXCHAN_BASEU_BRBH_S	0
++#define    PAS_DMA_TXCHAN_BASEU_BRBH(x)	(((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \
++					 PAS_DMA_TXCHAN_BASEU_BRBH_M)
++/* # of cache lines worth of buffer ring */
++#define    PAS_DMA_TXCHAN_BASEU_SIZ_M	0x3fff0000
++#define    PAS_DMA_TXCHAN_BASEU_SIZ_S	16		/* 0 = 16K */
++#define    PAS_DMA_TXCHAN_BASEU_SIZ(x)	(((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \
++					 PAS_DMA_TXCHAN_BASEU_SIZ_M)
++
++#define    PAS_STATUS_PCNT_M		0x000000000000ffffull
++#define    PAS_STATUS_PCNT_S		0
++#define    PAS_STATUS_DCNT_M		0x00000000ffff0000ull
++#define    PAS_STATUS_DCNT_S		16
++#define    PAS_STATUS_BPCNT_M		0x0000ffff00000000ull
++#define    PAS_STATUS_BPCNT_S		32
++#define    PAS_STATUS_CAUSE_M		0xf000000000000000ull
++#define    PAS_STATUS_TIMER		0x1000000000000000ull
++#define    PAS_STATUS_ERROR		0x2000000000000000ull
++#define    PAS_STATUS_SOFT		0x4000000000000000ull
++#define    PAS_STATUS_INT		0x8000000000000000ull
++
++#define PAS_IOB_DMA_RXCH_CFG(i)		(0x1100 + (i)*4)
++#define    PAS_IOB_DMA_RXCH_CFG_CNTTH_M		0x00000fff
++#define    PAS_IOB_DMA_RXCH_CFG_CNTTH_S		0
++#define    PAS_IOB_DMA_RXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \
++						 PAS_IOB_DMA_RXCH_CFG_CNTTH_M)
++#define PAS_IOB_DMA_TXCH_CFG(i)		(0x1200 + (i)*4)
++#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_M		0x00000fff
++#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_S		0
++#define    PAS_IOB_DMA_TXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \
++						 PAS_IOB_DMA_TXCH_CFG_CNTTH_M)
++#define PAS_IOB_DMA_RXCH_STAT(i)	(0x1300 + (i)*4)
++#define    PAS_IOB_DMA_RXCH_STAT_INTGEN	0x00001000
++#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_M	0x00000fff
++#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_S	0
++#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\
++						 PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
++#define PAS_IOB_DMA_TXCH_STAT(i)	(0x1400 + (i)*4)
++#define    PAS_IOB_DMA_TXCH_STAT_INTGEN	0x00001000
++#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_M	0x00000fff
++#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_S	0
++#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\
++						 PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
++#define PAS_IOB_DMA_RXCH_RESET(i)	(0x1500 + (i)*4)
++#define    PAS_IOB_DMA_RXCH_RESET_PCNT_M	0xffff0000
++#define    PAS_IOB_DMA_RXCH_RESET_PCNT_S	16
++#define    PAS_IOB_DMA_RXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \
++						 PAS_IOB_DMA_RXCH_RESET_PCNT_M)
++#define    PAS_IOB_DMA_RXCH_RESET_PCNTRST	0x00000020
++#define    PAS_IOB_DMA_RXCH_RESET_DCNTRST	0x00000010
++#define    PAS_IOB_DMA_RXCH_RESET_TINTC		0x00000008
++#define    PAS_IOB_DMA_RXCH_RESET_DINTC		0x00000004
++#define    PAS_IOB_DMA_RXCH_RESET_SINTC		0x00000002
++#define    PAS_IOB_DMA_RXCH_RESET_PINTC		0x00000001
++#define PAS_IOB_DMA_TXCH_RESET(i)	(0x1600 + (i)*4)
++#define    PAS_IOB_DMA_TXCH_RESET_PCNT_M	0xffff0000
++#define    PAS_IOB_DMA_TXCH_RESET_PCNT_S	16
++#define    PAS_IOB_DMA_TXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \
++						 PAS_IOB_DMA_TXCH_RESET_PCNT_M)
++#define    PAS_IOB_DMA_TXCH_RESET_PCNTRST	0x00000020
++#define    PAS_IOB_DMA_TXCH_RESET_DCNTRST	0x00000010
++#define    PAS_IOB_DMA_TXCH_RESET_TINTC		0x00000008
++#define    PAS_IOB_DMA_TXCH_RESET_DINTC		0x00000004
++#define    PAS_IOB_DMA_TXCH_RESET_SINTC		0x00000002
++#define    PAS_IOB_DMA_TXCH_RESET_PINTC		0x00000001
++
++#define PAS_IOB_DMA_COM_TIMEOUTCFG		0x1700
++#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M	0x00ffffff
++#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S	0
++#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(x)	(((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \
++						 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M)
++
++/* Transmit descriptor fields */
++#define	XCT_MACTX_T		0x8000000000000000ull
++#define	XCT_MACTX_ST		0x4000000000000000ull
++#define XCT_MACTX_NORES		0x0000000000000000ull
++#define XCT_MACTX_8BRES		0x1000000000000000ull
++#define XCT_MACTX_24BRES	0x2000000000000000ull
++#define XCT_MACTX_40BRES	0x3000000000000000ull
++#define XCT_MACTX_I		0x0800000000000000ull
++#define XCT_MACTX_O		0x0400000000000000ull
++#define XCT_MACTX_E		0x0200000000000000ull
++#define XCT_MACTX_VLAN_M	0x0180000000000000ull
++#define XCT_MACTX_VLAN_NOP	0x0000000000000000ull
++#define XCT_MACTX_VLAN_REMOVE	0x0080000000000000ull
++#define XCT_MACTX_VLAN_INSERT   0x0100000000000000ull
++#define XCT_MACTX_VLAN_REPLACE  0x0180000000000000ull
++#define XCT_MACTX_CRC_M		0x0060000000000000ull
++#define XCT_MACTX_CRC_NOP	0x0000000000000000ull
++#define XCT_MACTX_CRC_INSERT	0x0020000000000000ull
++#define XCT_MACTX_CRC_PAD	0x0040000000000000ull
++#define XCT_MACTX_CRC_REPLACE	0x0060000000000000ull
++#define XCT_MACTX_SS		0x0010000000000000ull
++#define XCT_MACTX_LLEN_M	0x00007fff00000000ull
++#define XCT_MACTX_LLEN_S	32ull
++#define XCT_MACTX_LLEN(x)	((((long)(x)) << XCT_MACTX_LLEN_S) & \
++				 XCT_MACTX_LLEN_M)
++#define XCT_MACTX_IPH_M		0x00000000f8000000ull
++#define XCT_MACTX_IPH_S		27ull
++#define XCT_MACTX_IPH(x)	((((long)(x)) << XCT_MACTX_IPH_S) & \
++				 XCT_MACTX_IPH_M)
++#define XCT_MACTX_IPO_M		0x0000000007c00000ull
++#define XCT_MACTX_IPO_S		22ull
++#define XCT_MACTX_IPO(x)	((((long)(x)) << XCT_MACTX_IPO_S) & \
++				 XCT_MACTX_IPO_M)
++#define XCT_MACTX_CSUM_M	0x0000000000000060ull
++#define XCT_MACTX_CSUM_NOP	0x0000000000000000ull
++#define XCT_MACTX_CSUM_TCP	0x0000000000000040ull
++#define XCT_MACTX_CSUM_UDP	0x0000000000000060ull
++#define XCT_MACTX_V6		0x0000000000000010ull
++#define XCT_MACTX_C		0x0000000000000004ull
++#define XCT_MACTX_AL2		0x0000000000000002ull
++
++#define XCT_PTR_T		0x8000000000000000ull
++#define XCT_PTR_LEN_M		0x7ffff00000000000ull
++#define XCT_PTR_LEN_S		44
++#define XCT_PTR_LEN(x)		((((long)(x)) << XCT_PTR_LEN_S) & \
++				 XCT_PTR_LEN_M)
++#define XCT_PTR_ADDR_M		0x00000fffffffffffull
++#define XCT_PTR_ADDR_S		0
++#define XCT_PTR_ADDR(x)		((((long)(x)) << XCT_PTR_ADDR_S) & \
++				 XCT_PTR_ADDR_M)
++
++/* Function descriptor fields */
++#define	XCT_FUN_T		0x8000000000000000ull
++#define	XCT_FUN_ST		0x4000000000000000ull
++#define XCT_FUN_NORES		0x0000000000000000ull
++#define XCT_FUN_8BRES		0x1000000000000000ull
++#define XCT_FUN_24BRES		0x2000000000000000ull
++#define XCT_FUN_40BRES		0x3000000000000000ull
++#define XCT_FUN_I		0x0800000000000000ull
++#define XCT_FUN_O		0x0400000000000000ull
++#define XCT_FUN_E		0x0200000000000000ull
++#define XCT_FUN_FUN_S		54
++#define XCT_FUN_FUN_M		0x01c0000000000000ull
++#define XCT_FUN_FUN(num)	((((long)(num)) << XCT_FUN_FUN_S) & \
++				XCT_FUN_FUN_M)
++#define XCT_FUN_CRM_NOP		0x0000000000000000ull
++#define XCT_FUN_CRM_SIG		0x0008000000000000ull
++#define XCT_FUN_CRM_ENC		0x0010000000000000ull
++#define XCT_FUN_CRM_DEC		0x0018000000000000ull
++#define XCT_FUN_CRM_SIG_ENC	0x0020000000000000ull
++#define XCT_FUN_CRM_ENC_SIG	0x0028000000000000ull
++#define XCT_FUN_CRM_SIG_DEC	0x0030000000000000ull
++#define XCT_FUN_CRM_DEC_SIG	0x0038000000000000ull
++#define XCT_FUN_LLEN_M		0x0007ffff00000000ull
++#define XCT_FUN_LLEN_S		32ULL
++#define XCT_FUN_LLEN(x)		((((long)(x)) << XCT_FUN_LLEN_S) & \
++				 XCT_FUN_LLEN_M)
++#define XCT_FUN_SHL_M		0x00000000f8000000ull
++#define XCT_FUN_SHL_S		27ull
++#define XCT_FUN_SHL(x)		((((long)(x)) << XCT_FUN_SHL_S) & \
++				 XCT_FUN_SHL_M)
++#define XCT_FUN_CHL_M		0x0000000007c00000ull
++#define XCT_FUN_CHL_S		22ull
++#define XCT_FUN_CHL(x)		((((long)(x)) << XCT_FUN_CHL_S) & \
++				 XCT_FUN_CHL_M)
++#define XCT_FUN_HSZ_M		0x00000000003c0000ull
++#define XCT_FUN_HSZ_S		18ull
++#define XCT_FUN_HSZ(x)		((((long)(x)) << XCT_FUN_HSZ_S) & \
++				 XCT_FUN_HSZ_M)
++#define XCT_FUN_ALG_DES		0x0000000000000000ull
++#define XCT_FUN_ALG_3DES	0x0000000000008000ull
++#define XCT_FUN_ALG_AES		0x0000000000010000ull
++#define XCT_FUN_ALG_ARC		0x0000000000018000ull
++#define XCT_FUN_ALG_KASUMI	0x0000000000020000ull
++#define XCT_FUN_BCM_ECB		0x0000000000000000ull
++#define XCT_FUN_BCM_CBC		0x0000000000001000ull
++#define XCT_FUN_BCM_CFB		0x0000000000002000ull
++#define XCT_FUN_BCM_OFB		0x0000000000003000ull
++#define XCT_FUN_BCM_CNT		0x0000000000003800ull
++#define XCT_FUN_BCM_KAS_F8	0x0000000000002800ull
++#define XCT_FUN_BCM_KAS_F9	0x0000000000001800ull
++#define XCT_FUN_BCP_NO_PAD	0x0000000000000000ull
++#define XCT_FUN_BCP_ZRO		0x0000000000000200ull
++#define XCT_FUN_BCP_PL		0x0000000000000400ull
++#define XCT_FUN_BCP_INCR	0x0000000000000600ull
++#define XCT_FUN_SIG_MD5		(0ull << 4)
++#define XCT_FUN_SIG_SHA1	(2ull << 4)
++#define XCT_FUN_SIG_HMAC_MD5	(8ull << 4)
++#define XCT_FUN_SIG_HMAC_SHA1	(10ull << 4)
++#define XCT_FUN_A		0x0000000000000008ull
++#define XCT_FUN_C		0x0000000000000004ull
++#define XCT_FUN_AL2		0x0000000000000002ull
++#define XCT_FUN_SE		0x0000000000000001ull
++
++#define XCT_FUN_SRC_PTR(len, addr)	(XCT_PTR_LEN(len) | XCT_PTR_ADDR(addr))
++#define XCT_FUN_DST_PTR(len, addr)	(XCT_FUN_SRC_PTR(len, addr) | \
++					0x8000000000000000ull)
++
++#define XCT_CTRL_HDR_FUN_NUM_M		0x01c0000000000000ull
++#define XCT_CTRL_HDR_FUN_NUM_S		54
++#define XCT_CTRL_HDR_LEN_M		0x0007ffff00000000ull
++#define XCT_CTRL_HDR_LEN_S		32
++#define XCT_CTRL_HDR_REG_M		0x00000000000000ffull
++#define XCT_CTRL_HDR_REG_S		0
++
++#define XCT_CTRL_HDR(funcN,len,reg)	(0x9400000000000000ull | \
++			((((long)(funcN)) << XCT_CTRL_HDR_FUN_NUM_S) \
++			& XCT_CTRL_HDR_FUN_NUM_M) | \
++			((((long)(len)) << \
++			XCT_CTRL_HDR_LEN_S) & XCT_CTRL_HDR_LEN_M) | \
++			((((long)(reg)) << \
++			XCT_CTRL_HDR_REG_S) & XCT_CTRL_HDR_REG_M))
++
++/* Function config command options */
++#define	DMA_CALGO_DES			0x00
++#define	DMA_CALGO_3DES			0x01
++#define	DMA_CALGO_AES			0x02
++#define	DMA_CALGO_ARC			0x03
++
++#define DMA_FN_CIV0			0x02
++#define DMA_FN_CIV1			0x03
++#define DMA_FN_HKEY0			0x0a
++
++#define XCT_PTR_ADDR_LEN(ptr)		((ptr) & XCT_PTR_ADDR_M), \
++			(((ptr) & XCT_PTR_LEN_M) >> XCT_PTR_LEN_S)
++
++#endif /* PASEMI_FNU_H */
+diff -urN linux-2.6.23.16.old/crypto/ocf/random.c linux-2.6.23.16/crypto/ocf/random.c
+--- linux-2.6.23.16.old/crypto/ocf/random.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/random.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,317 @@
++/*
++ * A system independant way of adding entropy to the kernels pool
++ * this way the drivers can focus on the real work and we can take
++ * care of pushing it to the appropriate place in the kernel.
++ *
++ * This should be fast and callable from timers/interrupts
++ *
++ * Written by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this product
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/version.h>
++#include <linux/unistd.h>
++#include <linux/poll.h>
++#include <linux/random.h>
++#include <cryptodev.h>
++
++#ifdef CONFIG_OCF_FIPS
++#include "rndtest.h"
++#endif
++
++#ifndef HAS_RANDOM_INPUT_WAIT
++#error "Please do not enable OCF_RANDOMHARVEST unless you have applied patches"
++#endif
++
++/*
++ * a hack to access the debug levels from the crypto driver
++ */
++extern int crypto_debug;
++#define debug crypto_debug
++
++/*
++ * a list of all registered random providers
++ */
++static LIST_HEAD(random_ops);
++static int started = 0;
++static int initted = 0;
++
++struct random_op {
++	struct list_head random_list;
++	u_int32_t driverid;
++	int (*read_random)(void *arg, u_int32_t *buf, int len);
++	void *arg;
++};
++
++static int random_proc(void *arg);
++
++static pid_t		randomproc = (pid_t) -1;
++static spinlock_t	random_lock;
++
++/*
++ * just init the spin locks
++ */
++static int
++crypto_random_init(void)
++{
++	spin_lock_init(&random_lock);
++	initted = 1;
++	return(0);
++}
++
++/*
++ * Add the given random reader to our list (if not present)
++ * and start the thread (if not already started)
++ *
++ * we have to assume that driver id is ok for now
++ */
++int
++crypto_rregister(
++	u_int32_t driverid,
++	int (*read_random)(void *arg, u_int32_t *buf, int len),
++	void *arg)
++{
++	unsigned long flags;
++	int ret = 0;
++	struct random_op	*rops, *tmp;
++
++	dprintk("%s,%d: %s(0x%x, %p, %p)\n", __FILE__, __LINE__,
++			__FUNCTION__, driverid, read_random, arg);
++
++	if (!initted)
++		crypto_random_init();
++
++#if 0
++	struct cryptocap	*cap;
++
++	cap = crypto_checkdriver(driverid);
++	if (!cap)
++		return EINVAL;
++#endif
++
++	list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
++		if (rops->driverid == driverid && rops->read_random == read_random)
++			return EEXIST;
++	}
++
++	rops = (struct random_op *) kmalloc(sizeof(*rops), GFP_KERNEL);
++	if (!rops)
++		return ENOMEM;
++
++	rops->driverid    = driverid;
++	rops->read_random = read_random;
++	rops->arg = arg;
++
++	spin_lock_irqsave(&random_lock, flags);
++	list_add_tail(&rops->random_list, &random_ops);
++	if (!started) {
++		randomproc = kernel_thread(random_proc, NULL, CLONE_FS|CLONE_FILES);
++		if (randomproc < 0) {
++			ret = randomproc;
++			printk("crypto: crypto_rregister cannot start random thread; "
++					"error %d", ret);
++		} else
++			started = 1;
++	}
++	spin_unlock_irqrestore(&random_lock, flags);
++
++	return ret;
++}
++EXPORT_SYMBOL(crypto_rregister);
++
++int
++crypto_runregister_all(u_int32_t driverid)
++{
++	struct random_op *rops, *tmp;
++	unsigned long flags;
++
++	dprintk("%s,%d: %s(0x%x)\n", __FILE__, __LINE__, __FUNCTION__, driverid);
++
++	list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
++		if (rops->driverid == driverid) {
++			list_del(&rops->random_list);
++			kfree(rops);
++		}
++	}
++
++	spin_lock_irqsave(&random_lock, flags);
++	if (list_empty(&random_ops) && started)
++		kill_proc(randomproc, SIGKILL, 1);
++	spin_unlock_irqrestore(&random_lock, flags);
++	return(0);
++}
++EXPORT_SYMBOL(crypto_runregister_all);
++
++/*
++ * while we can add entropy to random.c continue to read random data from
++ * the drivers and push it to random.
++ */
++static int
++random_proc(void *arg)
++{
++	int n;
++	int wantcnt;
++	int bufcnt = 0;
++	int retval = 0;
++	int *buf = NULL;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++	daemonize();
++	spin_lock_irq(&current->sigmask_lock);
++	sigemptyset(&current->blocked);
++	recalc_sigpending(current);
++	spin_unlock_irq(&current->sigmask_lock);
++	sprintf(current->comm, "ocf-random");
++#else
++	daemonize("ocf-random");
++	allow_signal(SIGKILL);
++#endif
++
++	(void) get_fs();
++	set_fs(get_ds());
++
++#ifdef CONFIG_OCF_FIPS
++#define NUM_INT (RNDTEST_NBYTES/sizeof(int))
++#else
++#define NUM_INT 32
++#endif
++
++	/*
++	 * some devices can transferr their RNG data direct into memory,
++	 * so make sure it is device friendly
++	 */
++	buf = kmalloc(NUM_INT * sizeof(int), GFP_DMA);
++	if (NULL == buf) {
++		printk("crypto: RNG could not allocate memory\n");
++		retval = -ENOMEM;
++		goto bad_alloc;
++	}
++
++	wantcnt = NUM_INT;   /* start by adding some entropy */
++
++	/*
++	 * its possible due to errors or driver removal that we no longer
++	 * have anything to do,  if so exit or we will consume all the CPU
++	 * doing nothing
++	 */
++	while (!list_empty(&random_ops)) {
++		struct random_op	*rops, *tmp;
++
++#ifdef CONFIG_OCF_FIPS
++		if (wantcnt)
++			wantcnt = NUM_INT; /* FIPs mode can do 20000 bits or none */
++#endif
++
++		/* see if we can get enough entropy to make the world
++		 * a better place.
++		 */
++		while (bufcnt < wantcnt && bufcnt < NUM_INT) {
++			list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
++
++				n = (*rops->read_random)(rops->arg, &buf[bufcnt],
++							 NUM_INT - bufcnt);
++
++				/* on failure remove the random number generator */
++				if (n == -1) {
++					list_del(&rops->random_list);
++					printk("crypto: RNG (driverid=0x%x) failed, disabling\n",
++							rops->driverid);
++					kfree(rops);
++				} else if (n > 0)
++					bufcnt += n;
++			}
++			/* give up CPU for a bit, just in case as this is a loop */
++			schedule();
++		}
++
++
++#ifdef CONFIG_OCF_FIPS
++		if (bufcnt > 0 && rndtest_buf((unsigned char *) &buf[0])) {
++			dprintk("crypto: buffer had fips errors, discarding\n");
++			bufcnt = 0;
++		}
++#endif
++
++		/*
++		 * if we have a certified buffer,  we can send some data
++		 * to /dev/random and move along
++		 */
++		if (bufcnt > 0) {
++			/* add what we have */
++			random_input_words(buf, bufcnt, bufcnt*sizeof(int)*8);
++			bufcnt = 0;
++		}
++
++		/* give up CPU for a bit so we don't hog while filling */
++		schedule();
++
++		/* wait for needing more */
++		wantcnt = random_input_wait();
++
++		if (wantcnt <= 0)
++			wantcnt = 0; /* try to get some info again */
++		else
++		 	/* round up to one word or we can loop forever */
++			wantcnt = (wantcnt + (sizeof(int)*8)) / (sizeof(int)*8);
++		if (wantcnt > NUM_INT) {
++			wantcnt = NUM_INT;
++		}
++
++		if (signal_pending(current)) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++			spin_lock_irq(&current->sigmask_lock);
++#endif
++			flush_signals(current);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++			spin_unlock_irq(&current->sigmask_lock);
++#endif
++		}
++	}
++	
++	kfree(buf);
++
++bad_alloc:
++	spin_lock_irq(&random_lock);
++	randomproc = (pid_t) -1;
++	started = 0;
++	spin_unlock_irq(&random_lock);
++
++	return retval;
++}
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/README linux-2.6.23.16/crypto/ocf/README
+--- linux-2.6.23.16.old/crypto/ocf/README	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/README	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,166 @@
++README - ocf-linux-20071215
++---------------------------
++
++This README provides instructions for getting ocf-linux compiled and
++operating in a generic linux environment.  For other information you
++might like to visit the home page for this project:
++
++    http://ocf-linux.sourceforge.net/
++
++Adding OCF to linux
++-------------------
++
++    Not much in this file for now,  just some notes.  I usually build
++    the ocf support as modules but it can be built into the kernel as
++    well.  To use it:
++
++    * mknod /dev/crypto c 10 70
++
++    * to add OCF to your kernel source,  you have two options.  Apply
++      the kernel specific patch:
++
++          cd linux-2.4*; gunzip < ocf-linux-24-XXXXXXXX.patch.gz | patch -p1
++          cd linux-2.6*; gunzip < ocf-linux-26-XXXXXXXX.patch.gz | patch -p1
++    
++      if you do one of the above,  then you can proceed to the next step,
++      or you can do the above process by hand with using the patches against
++      linux-2.4.35 and 2.6.23 to include the ocf code under crypto/ocf.
++      Here's how to add it:
++
++      for 2.4.35 (and later)
++
++          cd linux-2.4.35/crypto
++          tar xvzf ocf-linux.tar.gz
++          cd ..
++          patch -p1 < crypto/ocf/patches/linux-2.4.35-ocf.patch
++
++      for 2.6.23 (and later)
++
++          cd linux-2.6.23/crypto
++          tar xvzf ocf-linux.tar.gz
++          cd ..
++          patch -p1 < crypto/ocf/patches/linux-2.6.23-ocf.patch
++
++      It should be easy to take this patch and apply it to other more
++      recent versions of the kernels.  The same patches should also work
++      relatively easily on kernels as old as 2.6.11 and 2.4.18.
++      
++    * under 2.4 if you are on a non-x86 platform,  you may need to:
++
++        cp linux-2.X.x/include/asm-i386/kmap_types.h linux-2.X.x/include/asm-YYY
++
++      so that you can build the kernel crypto support needed for the cryptosoft
++      driver.
++
++    * For simplicity you should enable all the crypto support in your kernel
++      except for the test driver.  Likewise for the OCF options.  Do not
++      enable OCF crypto drivers for HW that you do not have (for example
++      ixp4xx will not compile on non-Xscale systems).
++
++    * make sure that cryptodev.h (from ocf-linux.tar.gz) is installed as
++      crypto/cryptodev.h in an include directory that is used for building
++      applications for your platform.  For example on a host system that
++      might be:
++
++              /usr/include/crypto/cryptodev.h
++
++    * patch your openssl-0.9.8g code with the openssl-0.9.8g.patch.
++      (NOTE: there is no longer a need to patch ssh). The patch is against:
++      openssl-0_9_8e
++
++      If you need a patch for an older version of openssl,  you should look
++      to older OCF releases.  This patch is unlikely to work on older
++      openssl versions.
++
++      openssl-0.9.8g.patch
++                - enables --with-cryptodev for non BSD systems
++                - adds -cpu option to openssl speed for calculating CPU load
++                  under linux
++                - fixes null pointer in openssl speed multi thread output.
++                - fixes test keys to work with linux crypto's more stringent
++                  key checking.
++                - adds MD5/SHA acceleration (Ronen Shitrit), only enabled
++                  with the --with-cryptodev-digests option
++                - fixes bug in engine code caching.
++
++    * build crypto-tools-XXXXXXXX.tar.gz if you want to try some of the BSD
++      tools for testing OCF (ie., cryptotest).
++
++How to load the OCF drivers
++---------------------------
++
++    First insert the base modules:
++
++        insmod ocf
++        insmod cryptodev
++
++    You can then install the software OCF driver with:
++
++        insmod cryptosoft
++
++    and one or more of the OCF HW drivers with:
++
++        insmod safe
++        insmod hifn7751
++        insmod ixp4xx
++        ...
++
++    all the drivers take a debug option to enable verbose debug so that
++    you can see what is going on.  For debug you load them as:
++
++        insmod ocf crypto_debug=1
++        insmod cryptodev cryptodev_debug=1
++        insmod cryptosoft swcr_debug=1
++
++    You may load more than one OCF crypto driver but then there is no guarantee
++    as to which will be used.
++
++    You can also enable debug at run time on 2.6 systems with the following:
++
++        echo 1 > /sys/module/ocf/parameters/crypto_debug
++        echo 1 > /sys/module/cryptodev/parameters/cryptodev_debug
++        echo 1 > /sys/module/cryptosoft/parameters/swcr_debug
++        echo 1 > /sys/module/hifn7751/parameters/hifn_debug
++        echo 1 > /sys/module/safe/parameters/safe_debug
++        echo 1 > /sys/module/ixp4xx/parameters/ixp_debug
++        ...
++
++Testing the OCF support
++-----------------------
++
++    run "cryptotest",  it should do a short test for a couple of
++    des packets.  If it does everything is working.
++
++    If this works,  then ssh will use the driver when invoked as:
++
++        ssh -c 3des username@host
++
++    to see for sure that it is operating, enable debug as defined above.
++
++    To get a better idea of performance run:
++
++        cryptotest 100 4096
++
++    There are more options to cryptotest,  see the help.
++
++    It is also possible to use openssl to test the speed of the crypto
++    drivers.
++
++        openssl speed -evp des -engine cryptodev -elapsed
++        openssl speed -evp des3 -engine cryptodev -elapsed
++        openssl speed -evp aes128 -engine cryptodev -elapsed
++
++    and multiple threads (10) with:
++
++        openssl speed -evp des -engine cryptodev -elapsed -multi 10
++        openssl speed -evp des3 -engine cryptodev -elapsed -multi 10
++        openssl speed -evp aes128 -engine cryptodev -elapsed -multi 10
++
++    for public key testing you can try:
++
++        cryptokeytest
++        openssl speed -engine cryptodev rsa -elapsed
++        openssl speed -engine cryptodev dsa -elapsed
++
++David McCullough
++david_mccullough@securecomputing.com
+diff -urN linux-2.6.23.16.old/crypto/ocf/rndtest.c linux-2.6.23.16/crypto/ocf/rndtest.c
+--- linux-2.6.23.16.old/crypto/ocf/rndtest.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/rndtest.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,300 @@
++/*	$OpenBSD$	*/
++
++/*
++ * OCF/Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ * The license and original author are listed below.
++ *
++ * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *	This product includes software developed by Jason L. Wright
++ * 4. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
++ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/wait.h>
++#include <linux/time.h>
++#include <linux/version.h>
++#include <linux/unistd.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/time.h>
++#include <cryptodev.h>
++#include "rndtest.h"
++
++static struct rndtest_stats rndstats;
++
++static	void rndtest_test(struct rndtest_state *);
++
++/* The tests themselves */
++static	int rndtest_monobit(struct rndtest_state *);
++static	int rndtest_runs(struct rndtest_state *);
++static	int rndtest_longruns(struct rndtest_state *);
++static	int rndtest_chi_4(struct rndtest_state *);
++
++static	int rndtest_runs_check(struct rndtest_state *, int, int *);
++static	void rndtest_runs_record(struct rndtest_state *, int, int *);
++
++static const struct rndtest_testfunc {
++	int (*test)(struct rndtest_state *);
++} rndtest_funcs[] = {
++	{ rndtest_monobit },
++	{ rndtest_runs },
++	{ rndtest_chi_4 },
++	{ rndtest_longruns },
++};
++
++#define	RNDTEST_NTESTS	(sizeof(rndtest_funcs)/sizeof(rndtest_funcs[0]))
++
++static void
++rndtest_test(struct rndtest_state *rsp)
++{
++	int i, rv = 0;
++
++	rndstats.rst_tests++;
++	for (i = 0; i < RNDTEST_NTESTS; i++)
++		rv |= (*rndtest_funcs[i].test)(rsp);
++	rsp->rs_discard = (rv != 0);
++}
++
++
++extern int crypto_debug;
++#define rndtest_verbose 2
++#define rndtest_report(rsp, failure, fmt, a...) \
++	{ if (failure || crypto_debug) { printk("rng_test: " fmt "\n", a); } else; }
++
++#define	RNDTEST_MONOBIT_MINONES	9725
++#define	RNDTEST_MONOBIT_MAXONES	10275
++
++static int
++rndtest_monobit(struct rndtest_state *rsp)
++{
++	int i, ones = 0, j;
++	u_int8_t r;
++
++	for (i = 0; i < RNDTEST_NBYTES; i++) {
++		r = rsp->rs_buf[i];
++		for (j = 0; j < 8; j++, r <<= 1)
++			if (r & 0x80)
++				ones++;
++	}
++	if (ones > RNDTEST_MONOBIT_MINONES &&
++	    ones < RNDTEST_MONOBIT_MAXONES) {
++		if (rndtest_verbose > 1)
++			rndtest_report(rsp, 0, "monobit pass (%d < %d < %d)",
++			    RNDTEST_MONOBIT_MINONES, ones,
++			    RNDTEST_MONOBIT_MAXONES);
++		return (0);
++	} else {
++		if (rndtest_verbose)
++			rndtest_report(rsp, 1,
++			    "monobit failed (%d ones)", ones);
++		rndstats.rst_monobit++;
++		return (-1);
++	}
++}
++
++#define	RNDTEST_RUNS_NINTERVAL	6
++
++static const struct rndtest_runs_tabs {
++	u_int16_t min, max;
++} rndtest_runs_tab[] = {
++	{ 2343, 2657 },
++	{ 1135, 1365 },
++	{ 542, 708 },
++	{ 251, 373 },
++	{ 111, 201 },
++	{ 111, 201 },
++};
++
++static int
++rndtest_runs(struct rndtest_state *rsp)
++{
++	int i, j, ones, zeros, rv = 0;
++	int onei[RNDTEST_RUNS_NINTERVAL], zeroi[RNDTEST_RUNS_NINTERVAL];
++	u_int8_t c;
++
++	bzero(onei, sizeof(onei));
++	bzero(zeroi, sizeof(zeroi));
++	ones = zeros = 0;
++	for (i = 0; i < RNDTEST_NBYTES; i++) {
++		c = rsp->rs_buf[i];
++		for (j = 0; j < 8; j++, c <<= 1) {
++			if (c & 0x80) {
++				ones++;
++				rndtest_runs_record(rsp, zeros, zeroi);
++				zeros = 0;
++			} else {
++				zeros++;
++				rndtest_runs_record(rsp, ones, onei);
++				ones = 0;
++			}
++		}
++	}
++	rndtest_runs_record(rsp, ones, onei);
++	rndtest_runs_record(rsp, zeros, zeroi);
++
++	rv |= rndtest_runs_check(rsp, 0, zeroi);
++	rv |= rndtest_runs_check(rsp, 1, onei);
++
++	if (rv)
++		rndstats.rst_runs++;
++
++	return (rv);
++}
++
++static void
++rndtest_runs_record(struct rndtest_state *rsp, int len, int *intrv)
++{
++	if (len == 0)
++		return;
++	if (len > RNDTEST_RUNS_NINTERVAL)
++		len = RNDTEST_RUNS_NINTERVAL;
++	len -= 1;
++	intrv[len]++;
++}
++
++static int
++rndtest_runs_check(struct rndtest_state *rsp, int val, int *src)
++{
++	int i, rv = 0;
++
++	for (i = 0; i < RNDTEST_RUNS_NINTERVAL; i++) {
++		if (src[i] < rndtest_runs_tab[i].min ||
++		    src[i] > rndtest_runs_tab[i].max) {
++			rndtest_report(rsp, 1,
++			    "%s interval %d failed (%d, %d-%d)",
++			    val ? "ones" : "zeros",
++			    i + 1, src[i], rndtest_runs_tab[i].min,
++			    rndtest_runs_tab[i].max);
++			rv = -1;
++		} else {
++			rndtest_report(rsp, 0,
++			    "runs pass %s interval %d (%d < %d < %d)",
++			    val ? "ones" : "zeros",
++			    i + 1, rndtest_runs_tab[i].min, src[i],
++			    rndtest_runs_tab[i].max);
++		}
++	}
++	return (rv);
++}
++
++static int
++rndtest_longruns(struct rndtest_state *rsp)
++{
++	int i, j, ones = 0, zeros = 0, maxones = 0, maxzeros = 0;
++	u_int8_t c;
++
++	for (i = 0; i < RNDTEST_NBYTES; i++) {
++		c = rsp->rs_buf[i];
++		for (j = 0; j < 8; j++, c <<= 1) {
++			if (c & 0x80) {
++				zeros = 0;
++				ones++;
++				if (ones > maxones)
++					maxones = ones;
++			} else {
++				ones = 0;
++				zeros++;
++				if (zeros > maxzeros)
++					maxzeros = zeros;
++			}
++		}
++	}
++
++	if (maxones < 26 && maxzeros < 26) {
++		rndtest_report(rsp, 0, "longruns pass (%d ones, %d zeros)",
++			maxones, maxzeros);
++		return (0);
++	} else {
++		rndtest_report(rsp, 1, "longruns fail (%d ones, %d zeros)",
++			maxones, maxzeros);
++		rndstats.rst_longruns++;
++		return (-1);
++	}
++}
++
++/*
++ * chi^2 test over 4 bits: (this is called the poker test in FIPS 140-2,
++ * but it is really the chi^2 test over 4 bits (the poker test as described
++ * by Knuth vol 2 is something different, and I take him as authoritative
++ * on nomenclature over NIST).
++ */
++#define	RNDTEST_CHI4_K	16
++#define	RNDTEST_CHI4_K_MASK	(RNDTEST_CHI4_K - 1)
++
++/*
++ * The unnormalized values are used so that we don't have to worry about
++ * fractional precision.  The "real" value is found by:
++ *	(V - 1562500) * (16 / 5000) = Vn   (where V is the unnormalized value)
++ */
++#define	RNDTEST_CHI4_VMIN	1563181		/* 2.1792 */
++#define	RNDTEST_CHI4_VMAX	1576929		/* 46.1728 */
++
++static int
++rndtest_chi_4(struct rndtest_state *rsp)
++{
++	unsigned int freq[RNDTEST_CHI4_K], i, sum;
++
++	for (i = 0; i < RNDTEST_CHI4_K; i++)
++		freq[i] = 0;
++
++	/* Get number of occurances of each 4 bit pattern */
++	for (i = 0; i < RNDTEST_NBYTES; i++) {
++		freq[(rsp->rs_buf[i] >> 4) & RNDTEST_CHI4_K_MASK]++;
++		freq[(rsp->rs_buf[i] >> 0) & RNDTEST_CHI4_K_MASK]++;
++	}
++
++	for (i = 0, sum = 0; i < RNDTEST_CHI4_K; i++)
++		sum += freq[i] * freq[i];
++
++	if (sum >= 1563181 && sum <= 1576929) {
++		rndtest_report(rsp, 0, "chi^2(4): pass (sum %u)", sum);
++		return (0);
++	} else {
++		rndtest_report(rsp, 1, "chi^2(4): failed (sum %u)", sum);
++		rndstats.rst_chi++;
++		return (-1);
++	}
++}
++
++int
++rndtest_buf(unsigned char *buf)
++{
++	struct rndtest_state rsp;
++
++	memset(&rsp, 0, sizeof(rsp));
++	rsp.rs_buf = buf;
++	rndtest_test(&rsp);
++	return(rsp.rs_discard);
++}
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/rndtest.h linux-2.6.23.16/crypto/ocf/rndtest.h
+--- linux-2.6.23.16.old/crypto/ocf/rndtest.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/rndtest.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,54 @@
++/*	$FreeBSD: src/sys/dev/rndtest/rndtest.h,v 1.1 2003/03/11 22:54:44 sam Exp $	*/
++/*	$OpenBSD$	*/
++
++/*
++ * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *	This product includes software developed by Jason L. Wright
++ * 4. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
++ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++
++/* Some of the tests depend on these values */
++#define	RNDTEST_NBYTES	2500
++#define	RNDTEST_NBITS	(8 * RNDTEST_NBYTES)
++
++struct rndtest_state {
++	int		rs_discard;	/* discard/accept random data */
++	u_int8_t	*rs_buf;
++};
++
++struct rndtest_stats {
++	u_int32_t	rst_discard;	/* number of bytes discarded */
++	u_int32_t	rst_tests;	/* number of test runs */
++	u_int32_t	rst_monobit;	/* monobit test failures */
++	u_int32_t	rst_runs;	/* 0/1 runs failures */
++	u_int32_t	rst_longruns;	/* longruns failures */
++	u_int32_t	rst_chi;	/* chi^2 failures */
++};
++
++extern int rndtest_buf(unsigned char *buf);
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/Makefile linux-2.6.23.16/crypto/ocf/safe/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/safe/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,12 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_SAFE) += safe.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/md5.c linux-2.6.23.16/crypto/ocf/safe/md5.c
+--- linux-2.6.23.16.old/crypto/ocf/safe/md5.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/md5.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,308 @@
++/*	$KAME: md5.c,v 1.5 2000/11/08 06:13:08 itojun Exp $	*/
++/*
++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#if 0
++#include <sys/cdefs.h>
++__FBSDID("$FreeBSD: src/sys/crypto/md5.c,v 1.9 2004/01/27 19:49:19 des Exp $");
++
++#include <sys/types.h>
++#include <sys/cdefs.h>
++#include <sys/time.h>
++#include <sys/systm.h>
++#include <crypto/md5.h>
++#endif
++
++#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
++
++#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
++#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
++#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
++#define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
++
++#define ROUND1(a, b, c, d, k, s, i) { \
++	(a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
++	(a) = SHIFT((a), (s)); \
++	(a) = (b) + (a); \
++}
++
++#define ROUND2(a, b, c, d, k, s, i) { \
++	(a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
++	(a) = SHIFT((a), (s)); \
++	(a) = (b) + (a); \
++}
++
++#define ROUND3(a, b, c, d, k, s, i) { \
++	(a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
++	(a) = SHIFT((a), (s)); \
++	(a) = (b) + (a); \
++}
++
++#define ROUND4(a, b, c, d, k, s, i) { \
++	(a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
++	(a) = SHIFT((a), (s)); \
++	(a) = (b) + (a); \
++}
++
++#define Sa	 7
++#define Sb	12
++#define Sc	17
++#define Sd	22
++
++#define Se	 5
++#define Sf	 9
++#define Sg	14
++#define Sh	20
++
++#define Si	 4
++#define Sj	11
++#define Sk	16
++#define Sl	23
++
++#define Sm	 6
++#define Sn	10
++#define So	15
++#define Sp	21
++
++#define MD5_A0	0x67452301
++#define MD5_B0	0xefcdab89
++#define MD5_C0	0x98badcfe
++#define MD5_D0	0x10325476
++
++/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
++static const u_int32_t T[65] = {
++	0,
++	0xd76aa478, 	0xe8c7b756,	0x242070db,	0xc1bdceee,
++	0xf57c0faf,	0x4787c62a, 	0xa8304613,	0xfd469501,
++	0x698098d8,	0x8b44f7af,	0xffff5bb1,	0x895cd7be,
++	0x6b901122, 	0xfd987193, 	0xa679438e,	0x49b40821,
++
++	0xf61e2562,	0xc040b340, 	0x265e5a51, 	0xe9b6c7aa,
++	0xd62f105d,	0x2441453,	0xd8a1e681,	0xe7d3fbc8,
++	0x21e1cde6,	0xc33707d6, 	0xf4d50d87, 	0x455a14ed,
++	0xa9e3e905,	0xfcefa3f8, 	0x676f02d9, 	0x8d2a4c8a,
++
++	0xfffa3942,	0x8771f681, 	0x6d9d6122, 	0xfde5380c,
++	0xa4beea44, 	0x4bdecfa9, 	0xf6bb4b60, 	0xbebfbc70,
++	0x289b7ec6, 	0xeaa127fa, 	0xd4ef3085,	0x4881d05,
++	0xd9d4d039, 	0xe6db99e5, 	0x1fa27cf8, 	0xc4ac5665,
++
++	0xf4292244, 	0x432aff97, 	0xab9423a7, 	0xfc93a039,
++	0x655b59c3, 	0x8f0ccc92, 	0xffeff47d, 	0x85845dd1,
++	0x6fa87e4f, 	0xfe2ce6e0, 	0xa3014314, 	0x4e0811a1,
++	0xf7537e82, 	0xbd3af235, 	0x2ad7d2bb, 	0xeb86d391,
++};
++
++static const u_int8_t md5_paddat[MD5_BUFLEN] = {
++	0x80,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,
++	0,	0,	0,	0,	0,	0,	0,	0,	
++};
++
++static void md5_calc(u_int8_t *, md5_ctxt *);
++
++void md5_init(ctxt)
++	md5_ctxt *ctxt;
++{
++	ctxt->md5_n = 0;
++	ctxt->md5_i = 0;
++	ctxt->md5_sta = MD5_A0;
++	ctxt->md5_stb = MD5_B0;
++	ctxt->md5_stc = MD5_C0;
++	ctxt->md5_std = MD5_D0;
++	bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf));
++}
++
++void md5_loop(ctxt, input, len)
++	md5_ctxt *ctxt;
++	u_int8_t *input;
++	u_int len; /* number of bytes */
++{
++	u_int gap, i;
++
++	ctxt->md5_n += len * 8; /* byte to bit */
++	gap = MD5_BUFLEN - ctxt->md5_i;
++
++	if (len >= gap) {
++		bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
++			gap);
++		md5_calc(ctxt->md5_buf, ctxt);
++
++		for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
++			md5_calc((u_int8_t *)(input + i), ctxt);
++		}
++		
++		ctxt->md5_i = len - i;
++		bcopy((void *)(input + i), (void *)ctxt->md5_buf, ctxt->md5_i);
++	} else {
++		bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
++			len);
++		ctxt->md5_i += len;
++	}
++}
++
++void md5_pad(ctxt)
++	md5_ctxt *ctxt;
++{
++	u_int gap;
++
++	/* Don't count up padding. Keep md5_n. */	
++	gap = MD5_BUFLEN - ctxt->md5_i;
++	if (gap > 8) {
++		bcopy(md5_paddat,
++		      (void *)(ctxt->md5_buf + ctxt->md5_i),
++		      gap - sizeof(ctxt->md5_n));
++	} else {
++		/* including gap == 8 */
++		bcopy(md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i),
++			gap);
++		md5_calc(ctxt->md5_buf, ctxt);
++		bcopy((md5_paddat + gap),
++		      (void *)ctxt->md5_buf,
++		      MD5_BUFLEN - sizeof(ctxt->md5_n));
++	}
++
++	/* 8 byte word */	
++#if BYTE_ORDER == LITTLE_ENDIAN
++	bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8);
++#endif
++#if BYTE_ORDER == BIG_ENDIAN
++	ctxt->md5_buf[56] = ctxt->md5_n8[7];
++	ctxt->md5_buf[57] = ctxt->md5_n8[6];
++	ctxt->md5_buf[58] = ctxt->md5_n8[5];
++	ctxt->md5_buf[59] = ctxt->md5_n8[4];
++	ctxt->md5_buf[60] = ctxt->md5_n8[3];
++	ctxt->md5_buf[61] = ctxt->md5_n8[2];
++	ctxt->md5_buf[62] = ctxt->md5_n8[1];
++	ctxt->md5_buf[63] = ctxt->md5_n8[0];
++#endif
++
++	md5_calc(ctxt->md5_buf, ctxt);
++}
++
++void md5_result(digest, ctxt)
++	u_int8_t *digest;
++	md5_ctxt *ctxt;
++{
++	/* 4 byte words */
++#if BYTE_ORDER == LITTLE_ENDIAN
++	bcopy(&ctxt->md5_st8[0], digest, 16);
++#endif
++#if BYTE_ORDER == BIG_ENDIAN
++	digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2];
++	digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0];
++	digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6];
++	digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4];
++	digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10];
++	digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8];
++	digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14];
++	digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12];
++#endif
++}
++
++static void md5_calc(b64, ctxt)
++	u_int8_t *b64;
++	md5_ctxt *ctxt;
++{
++	u_int32_t A = ctxt->md5_sta;
++	u_int32_t B = ctxt->md5_stb;
++	u_int32_t C = ctxt->md5_stc;
++	u_int32_t D = ctxt->md5_std;
++#if BYTE_ORDER == LITTLE_ENDIAN
++	u_int32_t *X = (u_int32_t *)b64;
++#endif	
++#if BYTE_ORDER == BIG_ENDIAN
++	/* 4 byte words */
++	/* what a brute force but fast! */
++	u_int32_t X[16];
++	u_int8_t *y = (u_int8_t *)X;
++	y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
++	y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
++	y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
++	y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
++	y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
++	y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
++	y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
++	y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
++	y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
++	y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
++	y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
++	y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
++	y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
++	y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
++	y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
++	y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
++#endif
++
++	ROUND1(A, B, C, D,  0, Sa,  1); ROUND1(D, A, B, C,  1, Sb,  2);
++	ROUND1(C, D, A, B,  2, Sc,  3); ROUND1(B, C, D, A,  3, Sd,  4);
++	ROUND1(A, B, C, D,  4, Sa,  5); ROUND1(D, A, B, C,  5, Sb,  6);
++	ROUND1(C, D, A, B,  6, Sc,  7); ROUND1(B, C, D, A,  7, Sd,  8);
++	ROUND1(A, B, C, D,  8, Sa,  9); ROUND1(D, A, B, C,  9, Sb, 10);
++	ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
++	ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
++	ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
++	
++	ROUND2(A, B, C, D,  1, Se, 17); ROUND2(D, A, B, C,  6, Sf, 18);
++	ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A,  0, Sh, 20);
++	ROUND2(A, B, C, D,  5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
++	ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A,  4, Sh, 24);
++	ROUND2(A, B, C, D,  9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
++	ROUND2(C, D, A, B,  3, Sg, 27); ROUND2(B, C, D, A,  8, Sh, 28);
++	ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C,  2, Sf, 30);
++	ROUND2(C, D, A, B,  7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
++
++	ROUND3(A, B, C, D,  5, Si, 33); ROUND3(D, A, B, C,  8, Sj, 34);
++	ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
++	ROUND3(A, B, C, D,  1, Si, 37); ROUND3(D, A, B, C,  4, Sj, 38);
++	ROUND3(C, D, A, B,  7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
++	ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C,  0, Sj, 42);
++	ROUND3(C, D, A, B,  3, Sk, 43); ROUND3(B, C, D, A,  6, Sl, 44);
++	ROUND3(A, B, C, D,  9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
++	ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A,  2, Sl, 48);
++	
++	ROUND4(A, B, C, D,  0, Sm, 49); ROUND4(D, A, B, C,  7, Sn, 50);	
++	ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A,  5, Sp, 52);	
++	ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C,  3, Sn, 54);	
++	ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A,  1, Sp, 56);	
++	ROUND4(A, B, C, D,  8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);	
++	ROUND4(C, D, A, B,  6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);	
++	ROUND4(A, B, C, D,  4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);	
++	ROUND4(C, D, A, B,  2, So, 63); ROUND4(B, C, D, A,  9, Sp, 64);
++
++	ctxt->md5_sta += A;
++	ctxt->md5_stb += B;
++	ctxt->md5_stc += C;
++	ctxt->md5_std += D;
++}
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/md5.h linux-2.6.23.16/crypto/ocf/safe/md5.h
+--- linux-2.6.23.16.old/crypto/ocf/safe/md5.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/md5.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,76 @@
++/*	$FreeBSD: src/sys/crypto/md5.h,v 1.4 2002/03/20 05:13:50 alfred Exp $	*/
++/*	$KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp $	*/
++
++/*
++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#ifndef _NETINET6_MD5_H_
++#define _NETINET6_MD5_H_
++
++#define MD5_BUFLEN	64
++
++typedef struct {
++	union {
++		u_int32_t	md5_state32[4];
++		u_int8_t	md5_state8[16];
++	} md5_st;
++
++#define md5_sta		md5_st.md5_state32[0]
++#define md5_stb		md5_st.md5_state32[1]
++#define md5_stc		md5_st.md5_state32[2]
++#define md5_std		md5_st.md5_state32[3]
++#define md5_st8		md5_st.md5_state8
++
++	union {
++		u_int64_t	md5_count64;
++		u_int8_t	md5_count8[8];
++	} md5_count;
++#define md5_n	md5_count.md5_count64
++#define md5_n8	md5_count.md5_count8
++
++	u_int	md5_i;
++	u_int8_t	md5_buf[MD5_BUFLEN];
++} md5_ctxt;
++
++extern void md5_init(md5_ctxt *);
++extern void md5_loop(md5_ctxt *, u_int8_t *, u_int);
++extern void md5_pad(md5_ctxt *);
++extern void md5_result(u_int8_t *, md5_ctxt *);
++
++/* compatibility */
++#define MD5_CTX		md5_ctxt
++#define MD5Init(x)	md5_init((x))
++#define MD5Update(x, y, z)	md5_loop((x), (y), (z))
++#define MD5Final(x, y) \
++do {				\
++	md5_pad((y));		\
++	md5_result((x), (y));	\
++} while (0)
++
++#endif /* ! _NETINET6_MD5_H_*/
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/safe.c linux-2.6.23.16/crypto/ocf/safe/safe.c
+--- linux-2.6.23.16.old/crypto/ocf/safe/safe.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/safe.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,2288 @@
++/*-
++ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2004-2007 David McCullough
++ * The license and original author are listed below.
++ *
++ * Copyright (c) 2003 Sam Leffler, Errno Consulting
++ * Copyright (c) 2003 Global Technology Associates, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++__FBSDID("$FreeBSD: src/sys/dev/safe/safe.c,v 1.18 2007/03/21 03:42:50 sam Exp $");
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/random.h>
++#include <linux/version.h>
++#include <linux/skbuff.h>
++#include <asm/io.h>
++
++/*
++ * SafeNet SafeXcel-1141 hardware crypto accelerator
++ */
++
++#include <cryptodev.h>
++#include <uio.h>
++#include <safe/safereg.h>
++#include <safe/safevar.h>
++
++#if 1
++#define	DPRINTF(a)	do { \
++						if (debug) { \
++							printk("%s: ", sc ? \
++								device_get_nameunit(sc->sc_dev) : "safe"); \
++							printk a; \
++						} \
++					} while (0)
++#else
++#define	DPRINTF(a)
++#endif
++
++/*
++ * until we find a cleaner way, include the BSD md5/sha1 code
++ * here
++ */
++#define HMAC_HACK 1
++#ifdef HMAC_HACK
++#define LITTLE_ENDIAN 1234
++#define BIG_ENDIAN 4321
++#ifdef __LITTLE_ENDIAN
++#define BYTE_ORDER LITTLE_ENDIAN
++#endif
++#ifdef __BIG_ENDIAN
++#define BYTE_ORDER BIG_ENDIAN
++#endif
++#include <safe/md5.h>
++#include <safe/md5.c>
++#include <safe/sha1.h>
++#include <safe/sha1.c>
++
++u_int8_t hmac_ipad_buffer[64] = {
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
++};
++
++u_int8_t hmac_opad_buffer[64] = {
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
++    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
++};
++#endif /* HMAC_HACK */
++
++/* add proc entry for this */
++struct safe_stats safestats;
++
++#define debug safe_debug
++int safe_debug = 0;
++module_param(safe_debug, int, 0644);
++MODULE_PARM_DESC(safe_debug, "Enable debug");
++
++static	void safe_callback(struct safe_softc *, struct safe_ringentry *);
++static	void safe_feed(struct safe_softc *, struct safe_ringentry *);
++#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
++static	void safe_rng_init(struct safe_softc *);
++int safe_rngbufsize = 8;		/* 32 bytes each read  */
++module_param(safe_rngbufsize, int, 0644);
++MODULE_PARM_DESC(safe_rngbufsize, "RNG polling buffer size (32-bit words)");
++int safe_rngmaxalarm = 8;		/* max alarms before reset */
++module_param(safe_rngmaxalarm, int, 0644);
++MODULE_PARM_DESC(safe_rngmaxalarm, "RNG max alarms before reset");
++#endif /* SAFE_NO_RNG */
++
++static void safe_totalreset(struct safe_softc *sc);
++static int safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op);
++static int safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op);
++static int safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re);
++static int safe_kprocess(device_t dev, struct cryptkop *krp, int hint);
++static int safe_kstart(struct safe_softc *sc);
++static int safe_ksigbits(struct safe_softc *sc, struct crparam *cr);
++static void safe_kfeed(struct safe_softc *sc);
++static void safe_kpoll(unsigned long arg);
++static void safe_kload_reg(struct safe_softc *sc, u_int32_t off,
++								u_int32_t len, struct crparam *n);
++
++static	int safe_newsession(device_t, u_int32_t *, struct cryptoini *);
++static	int safe_freesession(device_t, u_int64_t);
++static	int safe_process(device_t, struct cryptop *, int);
++
++static device_method_t safe_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	safe_newsession),
++	DEVMETHOD(cryptodev_freesession,safe_freesession),
++	DEVMETHOD(cryptodev_process,	safe_process),
++	DEVMETHOD(cryptodev_kprocess,	safe_kprocess),
++};
++
++#define	READ_REG(sc,r)			readl((sc)->sc_base_addr + (r))
++#define WRITE_REG(sc,r,val)		writel((val), (sc)->sc_base_addr + (r))
++
++#define SAFE_MAX_CHIPS 8
++static struct safe_softc *safe_chip_idx[SAFE_MAX_CHIPS];
++
++/*
++ * split our buffers up into safe DMAable byte fragments to avoid lockup
++ * bug in 1141 HW on rev 1.0.
++ */
++
++static int
++pci_map_linear(
++	struct safe_softc *sc,
++	struct safe_operand *buf,
++	void *addr,
++	int len)
++{
++	dma_addr_t tmp;
++	int chunk, tlen = len;
++
++	tmp = pci_map_single(sc->sc_pcidev, addr, len, PCI_DMA_BIDIRECTIONAL);
++
++	buf->mapsize += len;
++	while (len > 0) {
++		chunk = (len > sc->sc_max_dsize) ? sc->sc_max_dsize : len;
++		buf->segs[buf->nsegs].ds_addr = tmp;
++		buf->segs[buf->nsegs].ds_len  = chunk;
++		buf->segs[buf->nsegs].ds_tlen = tlen;
++		buf->nsegs++;
++		tmp  += chunk;
++		len  -= chunk;
++		tlen = 0;
++	}
++	return 0;
++}
++
++/*
++ * map in a given uio buffer (great on some arches :-)
++ */
++
++static int
++pci_map_uio(struct safe_softc *sc, struct safe_operand *buf, struct uio *uio)
++{
++	struct iovec *iov = uio->uio_iov;
++	int n;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	buf->mapsize = 0;
++	buf->nsegs = 0;
++
++	for (n = 0; n < uio->uio_iovcnt; n++) {
++		pci_map_linear(sc, buf, iov->iov_base, iov->iov_len);
++		iov++;
++	}
++
++	/* identify this buffer by the first segment */
++	buf->map = (void *) buf->segs[0].ds_addr;
++	return(0);
++}
++
++/*
++ * map in a given sk_buff
++ */
++
++static int
++pci_map_skb(struct safe_softc *sc,struct safe_operand *buf,struct sk_buff *skb)
++{
++	int i;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	buf->mapsize = 0;
++	buf->nsegs = 0;
++
++	pci_map_linear(sc, buf, skb->data, skb_headlen(skb));
++
++	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++		pci_map_linear(sc, buf,
++				page_address(skb_shinfo(skb)->frags[i].page) +
++				                        skb_shinfo(skb)->frags[i].page_offset,
++				skb_shinfo(skb)->frags[i].size);
++	}
++
++	/* identify this buffer by the first segment */
++	buf->map = (void *) buf->segs[0].ds_addr;
++	return(0);
++}
++
++
++#if 0 /* not needed at this time */
++static void
++pci_sync_operand(struct safe_softc *sc, struct safe_operand *buf)
++{
++	int i;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++	for (i = 0; i < buf->nsegs; i++)
++		pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
++				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
++}
++#endif
++
++static void
++pci_unmap_operand(struct safe_softc *sc, struct safe_operand *buf)
++{
++	int i;
++	DPRINTF(("%s()\n", __FUNCTION__));
++	for (i = 0; i < buf->nsegs; i++) {
++		if (buf->segs[i].ds_tlen) {
++			DPRINTF(("%s - unmap %d 0x%x %d\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
++			pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
++					buf->segs[i].ds_tlen, PCI_DMA_BIDIRECTIONAL);
++			DPRINTF(("%s - unmap %d 0x%x %d done\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
++		}
++		buf->segs[i].ds_addr = 0;
++		buf->segs[i].ds_len = 0;
++		buf->segs[i].ds_tlen = 0;
++	}
++	buf->nsegs = 0;
++	buf->mapsize = 0;
++	buf->map = 0;
++}
++
++
++/*
++ * SafeXcel Interrupt routine
++ */
++static irqreturn_t
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++safe_intr(int irq, void *arg)
++#else
++safe_intr(int irq, void *arg, struct pt_regs *regs)
++#endif
++{
++	struct safe_softc *sc = arg;
++	int stat;
++	unsigned long flags;
++
++	stat = READ_REG(sc, SAFE_HM_STAT);
++
++	DPRINTF(("%s(stat=0x%x)\n", __FUNCTION__, stat));
++
++	if (stat == 0)		/* shared irq, not for us */
++		return IRQ_NONE;
++
++	WRITE_REG(sc, SAFE_HI_CLR, stat);	/* IACK */
++
++	if ((stat & SAFE_INT_PE_DDONE)) {
++		/*
++		 * Descriptor(s) done; scan the ring and
++		 * process completed operations.
++		 */
++		spin_lock_irqsave(&sc->sc_ringmtx, flags);
++		while (sc->sc_back != sc->sc_front) {
++			struct safe_ringentry *re = sc->sc_back;
++
++#ifdef SAFE_DEBUG
++			if (debug) {
++				safe_dump_ringstate(sc, __func__);
++				safe_dump_request(sc, __func__, re);
++			}
++#endif
++			/*
++			 * safe_process marks ring entries that were allocated
++			 * but not used with a csr of zero.  This insures the
++			 * ring front pointer never needs to be set backwards
++			 * in the event that an entry is allocated but not used
++			 * because of a setup error.
++			 */
++			DPRINTF(("%s re->re_desc.d_csr=0x%x\n", __FUNCTION__, re->re_desc.d_csr));
++			if (re->re_desc.d_csr != 0) {
++				if (!SAFE_PE_CSR_IS_DONE(re->re_desc.d_csr)) {
++					DPRINTF(("%s !CSR_IS_DONE\n", __FUNCTION__));
++					break;
++				}
++				if (!SAFE_PE_LEN_IS_DONE(re->re_desc.d_len)) {
++					DPRINTF(("%s !LEN_IS_DONE\n", __FUNCTION__));
++					break;
++				}
++				sc->sc_nqchip--;
++				safe_callback(sc, re);
++			}
++			if (++(sc->sc_back) == sc->sc_ringtop)
++				sc->sc_back = sc->sc_ring;
++		}
++		spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
++	}
++
++	/*
++	 * Check to see if we got any DMA Error
++	 */
++	if (stat & SAFE_INT_PE_ERROR) {
++		printk("%s: dmaerr dmastat %08x\n", device_get_nameunit(sc->sc_dev),
++				(int)READ_REG(sc, SAFE_PE_DMASTAT));
++		safestats.st_dmaerr++;
++		safe_totalreset(sc);
++#if 0
++		safe_feed(sc);
++#endif
++	}
++
++	if (sc->sc_needwakeup) {		/* XXX check high watermark */
++		int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
++		DPRINTF(("%s: wakeup crypto %x\n", __func__,
++			sc->sc_needwakeup));
++		sc->sc_needwakeup &= ~wakeup;
++		crypto_unblock(sc->sc_cid, wakeup);
++	}
++	
++	return IRQ_HANDLED;
++}
++
++/*
++ * safe_feed() - post a request to chip
++ */
++static void
++safe_feed(struct safe_softc *sc, struct safe_ringentry *re)
++{
++	DPRINTF(("%s()\n", __FUNCTION__));
++#ifdef SAFE_DEBUG
++	if (debug) {
++		safe_dump_ringstate(sc, __func__);
++		safe_dump_request(sc, __func__, re);
++	}
++#endif
++	sc->sc_nqchip++;
++	if (sc->sc_nqchip > safestats.st_maxqchip)
++		safestats.st_maxqchip = sc->sc_nqchip;
++	/* poke h/w to check descriptor ring, any value can be written */
++	WRITE_REG(sc, SAFE_HI_RD_DESCR, 0);
++}
++
++#define	N(a)	(sizeof(a) / sizeof (a[0]))
++static void
++safe_setup_enckey(struct safe_session *ses, caddr_t key)
++{
++	int i;
++
++	bcopy(key, ses->ses_key, ses->ses_klen / 8);
++
++	/* PE is little-endian, insure proper byte order */
++	for (i = 0; i < N(ses->ses_key); i++)
++		ses->ses_key[i] = htole32(ses->ses_key[i]);
++}
++
++static void
++safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen)
++{
++#ifdef HMAC_HACK
++	MD5_CTX md5ctx;
++	SHA1_CTX sha1ctx;
++	int i;
++
++
++	for (i = 0; i < klen; i++)
++		key[i] ^= HMAC_IPAD_VAL;
++
++	if (algo == CRYPTO_MD5_HMAC) {
++		MD5Init(&md5ctx);
++		MD5Update(&md5ctx, key, klen);
++		MD5Update(&md5ctx, hmac_ipad_buffer, MD5_HMAC_BLOCK_LEN - klen);
++		bcopy(md5ctx.md5_st8, ses->ses_hminner, sizeof(md5ctx.md5_st8));
++	} else {
++		SHA1Init(&sha1ctx);
++		SHA1Update(&sha1ctx, key, klen);
++		SHA1Update(&sha1ctx, hmac_ipad_buffer,
++		    SHA1_HMAC_BLOCK_LEN - klen);
++		bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32));
++	}
++
++	for (i = 0; i < klen; i++)
++		key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
++
++	if (algo == CRYPTO_MD5_HMAC) {
++		MD5Init(&md5ctx);
++		MD5Update(&md5ctx, key, klen);
++		MD5Update(&md5ctx, hmac_opad_buffer, MD5_HMAC_BLOCK_LEN - klen);
++		bcopy(md5ctx.md5_st8, ses->ses_hmouter, sizeof(md5ctx.md5_st8));
++	} else {
++		SHA1Init(&sha1ctx);
++		SHA1Update(&sha1ctx, key, klen);
++		SHA1Update(&sha1ctx, hmac_opad_buffer,
++		    SHA1_HMAC_BLOCK_LEN - klen);
++		bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32));
++	}
++
++	for (i = 0; i < klen; i++)
++		key[i] ^= HMAC_OPAD_VAL;
++
++#if 0
++	/*
++	 * this code prevents SHA working on a BE host,
++	 * so it is obviously wrong.  I think the byte
++	 * swap setup we do with the chip fixes this for us
++	 */
++
++	/* PE is little-endian, insure proper byte order */
++	for (i = 0; i < N(ses->ses_hminner); i++) {
++		ses->ses_hminner[i] = htole32(ses->ses_hminner[i]);
++		ses->ses_hmouter[i] = htole32(ses->ses_hmouter[i]);
++	}
++#endif
++#else /* HMAC_HACK */
++	printk("safe: md5/sha not implemented\n");
++#endif /* HMAC_HACK */
++}
++#undef N
++
++/*
++ * Allocate a new 'session' and return an encoded session id.  'sidp'
++ * contains our registration id, and should contain an encoded session
++ * id on successful allocation.
++ */
++static int
++safe_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
++{
++	struct safe_softc *sc = device_get_softc(dev);
++	struct cryptoini *c, *encini = NULL, *macini = NULL;
++	struct safe_session *ses = NULL;
++	int sesn;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (sidp == NULL || cri == NULL || sc == NULL)
++		return (EINVAL);
++
++	for (c = cri; c != NULL; c = c->cri_next) {
++		if (c->cri_alg == CRYPTO_MD5_HMAC ||
++		    c->cri_alg == CRYPTO_SHA1_HMAC ||
++		    c->cri_alg == CRYPTO_NULL_HMAC) {
++			if (macini)
++				return (EINVAL);
++			macini = c;
++		} else if (c->cri_alg == CRYPTO_DES_CBC ||
++		    c->cri_alg == CRYPTO_3DES_CBC ||
++		    c->cri_alg == CRYPTO_AES_CBC ||
++		    c->cri_alg == CRYPTO_NULL_CBC) {
++			if (encini)
++				return (EINVAL);
++			encini = c;
++		} else
++			return (EINVAL);
++	}
++	if (encini == NULL && macini == NULL)
++		return (EINVAL);
++	if (encini) {			/* validate key length */
++		switch (encini->cri_alg) {
++		case CRYPTO_DES_CBC:
++			if (encini->cri_klen != 64)
++				return (EINVAL);
++			break;
++		case CRYPTO_3DES_CBC:
++			if (encini->cri_klen != 192)
++				return (EINVAL);
++			break;
++		case CRYPTO_AES_CBC:
++			if (encini->cri_klen != 128 &&
++			    encini->cri_klen != 192 &&
++			    encini->cri_klen != 256)
++				return (EINVAL);
++			break;
++		}
++	}
++
++	if (sc->sc_sessions == NULL) {
++		ses = sc->sc_sessions = (struct safe_session *)
++			kmalloc(sizeof(struct safe_session), SLAB_ATOMIC);
++		if (ses == NULL)
++			return (ENOMEM);
++		memset(ses, 0, sizeof(struct safe_session));
++		sesn = 0;
++		sc->sc_nsessions = 1;
++	} else {
++		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
++			if (sc->sc_sessions[sesn].ses_used == 0) {
++				ses = &sc->sc_sessions[sesn];
++				break;
++			}
++		}
++
++		if (ses == NULL) {
++			sesn = sc->sc_nsessions;
++			ses = (struct safe_session *)
++				kmalloc((sesn + 1) * sizeof(struct safe_session), SLAB_ATOMIC);
++			if (ses == NULL)
++				return (ENOMEM);
++			memset(ses, 0, (sesn + 1) * sizeof(struct safe_session));
++			bcopy(sc->sc_sessions, ses, sesn *
++			    sizeof(struct safe_session));
++			bzero(sc->sc_sessions, sesn *
++			    sizeof(struct safe_session));
++			kfree(sc->sc_sessions);
++			sc->sc_sessions = ses;
++			ses = &sc->sc_sessions[sesn];
++			sc->sc_nsessions++;
++		}
++	}
++
++	bzero(ses, sizeof(struct safe_session));
++	ses->ses_used = 1;
++
++	if (encini) {
++		/* get an IV */
++		/* XXX may read fewer than requested */
++		read_random(ses->ses_iv, sizeof(ses->ses_iv));
++
++		ses->ses_klen = encini->cri_klen;
++		if (encini->cri_key != NULL)
++			safe_setup_enckey(ses, encini->cri_key);
++	}
++
++	if (macini) {
++		ses->ses_mlen = macini->cri_mlen;
++		if (ses->ses_mlen == 0) {
++			if (macini->cri_alg == CRYPTO_MD5_HMAC)
++				ses->ses_mlen = MD5_HASH_LEN;
++			else
++				ses->ses_mlen = SHA1_HASH_LEN;
++		}
++
++		if (macini->cri_key != NULL) {
++			safe_setup_mackey(ses, macini->cri_alg, macini->cri_key,
++			    macini->cri_klen / 8);
++		}
++	}
++
++	*sidp = SAFE_SID(device_get_unit(sc->sc_dev), sesn);
++	return (0);
++}
++
++/*
++ * Deallocate a session.
++ */
++static int
++safe_freesession(device_t dev, u_int64_t tid)
++{
++	struct safe_softc *sc = device_get_softc(dev);
++	int session, ret;
++	u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (sc == NULL)
++		return (EINVAL);
++
++	session = SAFE_SESSION(sid);
++	if (session < sc->sc_nsessions) {
++		bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
++		ret = 0;
++	} else
++		ret = EINVAL;
++	return (ret);
++}
++
++
++static int
++safe_process(device_t dev, struct cryptop *crp, int hint)
++{
++	struct safe_softc *sc = device_get_softc(dev);
++	int err = 0, i, nicealign, uniform;
++	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
++	int bypass, oplen, ivsize;
++	caddr_t iv;
++	int16_t coffset;
++	struct safe_session *ses;
++	struct safe_ringentry *re;
++	struct safe_sarec *sa;
++	struct safe_pdesc *pd;
++	u_int32_t cmd0, cmd1, staterec;
++	unsigned long flags;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
++		safestats.st_invalid++;
++		return (EINVAL);
++	}
++	if (SAFE_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
++		safestats.st_badsession++;
++		return (EINVAL);
++	}
++
++	spin_lock_irqsave(&sc->sc_ringmtx, flags);
++	if (sc->sc_front == sc->sc_back && sc->sc_nqchip != 0) {
++		safestats.st_ringfull++;
++		sc->sc_needwakeup |= CRYPTO_SYMQ;
++		spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
++		return (ERESTART);
++	}
++	re = sc->sc_front;
++
++	staterec = re->re_sa.sa_staterec;	/* save */
++	/* NB: zero everything but the PE descriptor */
++	bzero(&re->re_sa, sizeof(struct safe_ringentry) - sizeof(re->re_desc));
++	re->re_sa.sa_staterec = staterec;	/* restore */
++
++	re->re_crp = crp;
++	re->re_sesn = SAFE_SESSION(crp->crp_sid);
++
++	re->re_src.nsegs = 0;
++	re->re_dst.nsegs = 0;
++
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		re->re_src_skb = (struct sk_buff *)crp->crp_buf;
++		re->re_dst_skb = (struct sk_buff *)crp->crp_buf;
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		re->re_src_io = (struct uio *)crp->crp_buf;
++		re->re_dst_io = (struct uio *)crp->crp_buf;
++	} else {
++		safestats.st_badflags++;
++		err = EINVAL;
++		goto errout;	/* XXX we don't handle contiguous blocks! */
++	}
++
++	sa = &re->re_sa;
++	ses = &sc->sc_sessions[re->re_sesn];
++
++	crd1 = crp->crp_desc;
++	if (crd1 == NULL) {
++		safestats.st_nodesc++;
++		err = EINVAL;
++		goto errout;
++	}
++	crd2 = crd1->crd_next;
++
++	cmd0 = SAFE_SA_CMD0_BASIC;		/* basic group operation */
++	cmd1 = 0;
++	if (crd2 == NULL) {
++		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
++		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
++		    crd1->crd_alg == CRYPTO_NULL_HMAC) {
++			maccrd = crd1;
++			enccrd = NULL;
++			cmd0 |= SAFE_SA_CMD0_OP_HASH;
++		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
++		    crd1->crd_alg == CRYPTO_3DES_CBC ||
++		    crd1->crd_alg == CRYPTO_AES_CBC ||
++		    crd1->crd_alg == CRYPTO_NULL_CBC) {
++			maccrd = NULL;
++			enccrd = crd1;
++			cmd0 |= SAFE_SA_CMD0_OP_CRYPT;
++		} else {
++			safestats.st_badalg++;
++			err = EINVAL;
++			goto errout;
++		}
++	} else {
++		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
++		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
++		    crd1->crd_alg == CRYPTO_NULL_HMAC) &&
++		    (crd2->crd_alg == CRYPTO_DES_CBC ||
++			crd2->crd_alg == CRYPTO_3DES_CBC ||
++		        crd2->crd_alg == CRYPTO_AES_CBC ||
++		        crd2->crd_alg == CRYPTO_NULL_CBC) &&
++		    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
++			maccrd = crd1;
++			enccrd = crd2;
++		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
++		    crd1->crd_alg == CRYPTO_3DES_CBC ||
++		    crd1->crd_alg == CRYPTO_AES_CBC ||
++		    crd1->crd_alg == CRYPTO_NULL_CBC) &&
++		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
++			crd2->crd_alg == CRYPTO_SHA1_HMAC ||
++			crd2->crd_alg == CRYPTO_NULL_HMAC) &&
++		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
++			enccrd = crd1;
++			maccrd = crd2;
++		} else {
++			safestats.st_badalg++;
++			err = EINVAL;
++			goto errout;
++		}
++		cmd0 |= SAFE_SA_CMD0_OP_BOTH;
++	}
++
++	if (enccrd) {
++		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
++			safe_setup_enckey(ses, enccrd->crd_key);
++
++		if (enccrd->crd_alg == CRYPTO_DES_CBC) {
++			cmd0 |= SAFE_SA_CMD0_DES;
++			cmd1 |= SAFE_SA_CMD1_CBC;
++			ivsize = 2*sizeof(u_int32_t);
++		} else if (enccrd->crd_alg == CRYPTO_3DES_CBC) {
++			cmd0 |= SAFE_SA_CMD0_3DES;
++			cmd1 |= SAFE_SA_CMD1_CBC;
++			ivsize = 2*sizeof(u_int32_t);
++		} else if (enccrd->crd_alg == CRYPTO_AES_CBC) {
++			cmd0 |= SAFE_SA_CMD0_AES;
++			cmd1 |= SAFE_SA_CMD1_CBC;
++			if (ses->ses_klen == 128)
++			     cmd1 |=  SAFE_SA_CMD1_AES128;
++			else if (ses->ses_klen == 192)
++			     cmd1 |=  SAFE_SA_CMD1_AES192;
++			else
++			     cmd1 |=  SAFE_SA_CMD1_AES256;
++			ivsize = 4*sizeof(u_int32_t);
++		} else {
++			cmd0 |= SAFE_SA_CMD0_CRYPT_NULL;
++			ivsize = 0;
++		}
++
++		/*
++		 * Setup encrypt/decrypt state.  When using basic ops
++		 * we can't use an inline IV because hash/crypt offset
++		 * must be from the end of the IV to the start of the
++		 * crypt data and this leaves out the preceding header
++		 * from the hash calculation.  Instead we place the IV
++		 * in the state record and set the hash/crypt offset to
++		 * copy both the header+IV.
++		 */
++		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
++			cmd0 |= SAFE_SA_CMD0_OUTBOUND;
++
++			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
++				iv = enccrd->crd_iv;
++			else
++				iv = (caddr_t) ses->ses_iv;
++			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
++				crypto_copyback(crp->crp_flags, crp->crp_buf,
++				    enccrd->crd_inject, ivsize, iv);
++			}
++			bcopy(iv, re->re_sastate.sa_saved_iv, ivsize);
++			/* make iv LE */
++			for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
++				re->re_sastate.sa_saved_iv[i] =
++					cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
++			cmd0 |= SAFE_SA_CMD0_IVLD_STATE | SAFE_SA_CMD0_SAVEIV;
++			re->re_flags |= SAFE_QFLAGS_COPYOUTIV;
++		} else {
++			cmd0 |= SAFE_SA_CMD0_INBOUND;
++
++			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
++				bcopy(enccrd->crd_iv,
++					re->re_sastate.sa_saved_iv, ivsize);
++			} else {
++				crypto_copydata(crp->crp_flags, crp->crp_buf,
++				    enccrd->crd_inject, ivsize,
++				    (caddr_t)re->re_sastate.sa_saved_iv);
++			}
++			/* make iv LE */
++			for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
++				re->re_sastate.sa_saved_iv[i] =
++					cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
++			cmd0 |= SAFE_SA_CMD0_IVLD_STATE;
++		}
++		/*
++		 * For basic encryption use the zero pad algorithm.
++		 * This pads results to an 8-byte boundary and
++		 * suppresses padding verification for inbound (i.e.
++		 * decrypt) operations.
++		 *
++		 * NB: Not sure if the 8-byte pad boundary is a problem.
++		 */
++		cmd0 |= SAFE_SA_CMD0_PAD_ZERO;
++
++		/* XXX assert key bufs have the same size */
++		bcopy(ses->ses_key, sa->sa_key, sizeof(sa->sa_key));
++	}
++
++	if (maccrd) {
++		if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
++			safe_setup_mackey(ses, maccrd->crd_alg,
++			    maccrd->crd_key, maccrd->crd_klen / 8);
++		}
++
++		if (maccrd->crd_alg == CRYPTO_MD5_HMAC) {
++			cmd0 |= SAFE_SA_CMD0_MD5;
++			cmd1 |= SAFE_SA_CMD1_HMAC;	/* NB: enable HMAC */
++		} else if (maccrd->crd_alg == CRYPTO_SHA1_HMAC) {
++			cmd0 |= SAFE_SA_CMD0_SHA1;
++			cmd1 |= SAFE_SA_CMD1_HMAC;	/* NB: enable HMAC */
++		} else {
++			cmd0 |= SAFE_SA_CMD0_HASH_NULL;
++		}
++		/*
++		 * Digest data is loaded from the SA and the hash
++		 * result is saved to the state block where we
++		 * retrieve it for return to the caller.
++		 */
++		/* XXX assert digest bufs have the same size */
++		bcopy(ses->ses_hminner, sa->sa_indigest,
++			sizeof(sa->sa_indigest));
++		bcopy(ses->ses_hmouter, sa->sa_outdigest,
++			sizeof(sa->sa_outdigest));
++
++		cmd0 |= SAFE_SA_CMD0_HSLD_SA | SAFE_SA_CMD0_SAVEHASH;
++		re->re_flags |= SAFE_QFLAGS_COPYOUTICV;
++	}
++
++	if (enccrd && maccrd) {
++		/*
++		 * The offset from hash data to the start of
++		 * crypt data is the difference in the skips.
++		 */
++		bypass = maccrd->crd_skip;
++		coffset = enccrd->crd_skip - maccrd->crd_skip;
++		if (coffset < 0) {
++			DPRINTF(("%s: hash does not precede crypt; "
++				"mac skip %u enc skip %u\n",
++				__func__, maccrd->crd_skip, enccrd->crd_skip));
++			safestats.st_skipmismatch++;
++			err = EINVAL;
++			goto errout;
++		}
++		oplen = enccrd->crd_skip + enccrd->crd_len;
++		if (maccrd->crd_skip + maccrd->crd_len != oplen) {
++			DPRINTF(("%s: hash amount %u != crypt amount %u\n",
++				__func__, maccrd->crd_skip + maccrd->crd_len,
++				oplen));
++			safestats.st_lenmismatch++;
++			err = EINVAL;
++			goto errout;
++		}
++#ifdef SAFE_DEBUG
++		if (debug) {
++			printf("mac: skip %d, len %d, inject %d\n",
++			    maccrd->crd_skip, maccrd->crd_len,
++			    maccrd->crd_inject);
++			printf("enc: skip %d, len %d, inject %d\n",
++			    enccrd->crd_skip, enccrd->crd_len,
++			    enccrd->crd_inject);
++			printf("bypass %d coffset %d oplen %d\n",
++				bypass, coffset, oplen);
++		}
++#endif
++		if (coffset & 3) {	/* offset must be 32-bit aligned */
++			DPRINTF(("%s: coffset %u misaligned\n",
++				__func__, coffset));
++			safestats.st_coffmisaligned++;
++			err = EINVAL;
++			goto errout;
++		}
++		coffset >>= 2;
++		if (coffset > 255) {	/* offset must be <256 dwords */
++			DPRINTF(("%s: coffset %u too big\n",
++				__func__, coffset));
++			safestats.st_cofftoobig++;
++			err = EINVAL;
++			goto errout;
++		}
++		/*
++		 * Tell the hardware to copy the header to the output.
++		 * The header is defined as the data from the end of
++		 * the bypass to the start of data to be encrypted. 
++		 * Typically this is the inline IV.  Note that you need
++		 * to do this even if src+dst are the same; it appears
++		 * that w/o this bit the crypted data is written
++		 * immediately after the bypass data.
++		 */
++		cmd1 |= SAFE_SA_CMD1_HDRCOPY;
++		/*
++		 * Disable IP header mutable bit handling.  This is
++		 * needed to get correct HMAC calculations.
++		 */
++		cmd1 |= SAFE_SA_CMD1_MUTABLE;
++	} else {
++		if (enccrd) {
++			bypass = enccrd->crd_skip;
++			oplen = bypass + enccrd->crd_len;
++		} else {
++			bypass = maccrd->crd_skip;
++			oplen = bypass + maccrd->crd_len;
++		}
++		coffset = 0;
++	}
++	/* XXX verify multiple of 4 when using s/g */
++	if (bypass > 96) {		/* bypass offset must be <= 96 bytes */
++		DPRINTF(("%s: bypass %u too big\n", __func__, bypass));
++		safestats.st_bypasstoobig++;
++		err = EINVAL;
++		goto errout;
++	}
++
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		if (pci_map_skb(sc, &re->re_src, re->re_src_skb)) {
++			safestats.st_noload++;
++			err = ENOMEM;
++			goto errout;
++		}
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		if (pci_map_uio(sc, &re->re_src, re->re_src_io)) {
++			safestats.st_noload++;
++			err = ENOMEM;
++			goto errout;
++		}
++	}
++	nicealign = safe_dmamap_aligned(sc, &re->re_src);
++	uniform = safe_dmamap_uniform(sc, &re->re_src);
++
++	DPRINTF(("src nicealign %u uniform %u nsegs %u\n",
++		nicealign, uniform, re->re_src.nsegs));
++	if (re->re_src.nsegs > 1) {
++		re->re_desc.d_src = sc->sc_spalloc.dma_paddr +
++			((caddr_t) sc->sc_spfree - (caddr_t) sc->sc_spring);
++		for (i = 0; i < re->re_src_nsegs; i++) {
++			/* NB: no need to check if there's space */
++			pd = sc->sc_spfree;
++			if (++(sc->sc_spfree) == sc->sc_springtop)
++				sc->sc_spfree = sc->sc_spring;
++
++			KASSERT((pd->pd_flags&3) == 0 ||
++				(pd->pd_flags&3) == SAFE_PD_DONE,
++				("bogus source particle descriptor; flags %x",
++				pd->pd_flags));
++			pd->pd_addr = re->re_src_segs[i].ds_addr;
++			pd->pd_size = re->re_src_segs[i].ds_len;
++			pd->pd_flags = SAFE_PD_READY;
++		}
++		cmd0 |= SAFE_SA_CMD0_IGATHER;
++	} else {
++		/*
++		 * No need for gather, reference the operand directly.
++		 */
++		re->re_desc.d_src = re->re_src_segs[0].ds_addr;
++	}
++
++	if (enccrd == NULL && maccrd != NULL) {
++		/*
++		 * Hash op; no destination needed.
++		 */
++	} else {
++		if (crp->crp_flags & (CRYPTO_F_IOV|CRYPTO_F_SKBUF)) {
++			if (!nicealign) {
++				safestats.st_iovmisaligned++;
++				err = EINVAL;
++				goto errout;
++			}
++			if (uniform != 1) {
++				device_printf(sc->sc_dev, "!uniform source\n");
++				if (!uniform) {
++					/*
++					 * There's no way to handle the DMA
++					 * requirements with this uio.  We
++					 * could create a separate DMA area for
++					 * the result and then copy it back,
++					 * but for now we just bail and return
++					 * an error.  Note that uio requests
++					 * > SAFE_MAX_DSIZE are handled because
++					 * the DMA map and segment list for the
++					 * destination wil result in a
++					 * destination particle list that does
++					 * the necessary scatter DMA.
++					 */ 
++					safestats.st_iovnotuniform++;
++					err = EINVAL;
++					goto errout;
++				}
++			} else
++				re->re_dst = re->re_src;
++		} else {
++			safestats.st_badflags++;
++			err = EINVAL;
++			goto errout;
++		}
++
++		if (re->re_dst.nsegs > 1) {
++			re->re_desc.d_dst = sc->sc_dpalloc.dma_paddr +
++			    ((caddr_t) sc->sc_dpfree - (caddr_t) sc->sc_dpring);
++			for (i = 0; i < re->re_dst_nsegs; i++) {
++				pd = sc->sc_dpfree;
++				KASSERT((pd->pd_flags&3) == 0 ||
++					(pd->pd_flags&3) == SAFE_PD_DONE,
++					("bogus dest particle descriptor; flags %x",
++						pd->pd_flags));
++				if (++(sc->sc_dpfree) == sc->sc_dpringtop)
++					sc->sc_dpfree = sc->sc_dpring;
++				pd->pd_addr = re->re_dst_segs[i].ds_addr;
++				pd->pd_flags = SAFE_PD_READY;
++			}
++			cmd0 |= SAFE_SA_CMD0_OSCATTER;
++		} else {
++			/*
++			 * No need for scatter, reference the operand directly.
++			 */
++			re->re_desc.d_dst = re->re_dst_segs[0].ds_addr;
++		}
++	}
++
++	/*
++	 * All done with setup; fillin the SA command words
++	 * and the packet engine descriptor.  The operation
++	 * is now ready for submission to the hardware.
++	 */
++	sa->sa_cmd0 = cmd0 | SAFE_SA_CMD0_IPCI | SAFE_SA_CMD0_OPCI;
++	sa->sa_cmd1 = cmd1
++		    | (coffset << SAFE_SA_CMD1_OFFSET_S)
++		    | SAFE_SA_CMD1_SAREV1	/* Rev 1 SA data structure */
++		    | SAFE_SA_CMD1_SRPCI
++		    ;
++	/*
++	 * NB: the order of writes is important here.  In case the
++	 * chip is scanning the ring because of an outstanding request
++	 * it might nab this one too.  In that case we need to make
++	 * sure the setup is complete before we write the length
++	 * field of the descriptor as it signals the descriptor is
++	 * ready for processing.
++	 */
++	re->re_desc.d_csr = SAFE_PE_CSR_READY | SAFE_PE_CSR_SAPCI;
++	if (maccrd)
++		re->re_desc.d_csr |= SAFE_PE_CSR_LOADSA | SAFE_PE_CSR_HASHFINAL;
++	wmb();
++	re->re_desc.d_len = oplen
++			  | SAFE_PE_LEN_READY
++			  | (bypass << SAFE_PE_LEN_BYPASS_S)
++			  ;
++
++	safestats.st_ipackets++;
++	safestats.st_ibytes += oplen;
++
++	if (++(sc->sc_front) == sc->sc_ringtop)
++		sc->sc_front = sc->sc_ring;
++
++	/* XXX honor batching */
++	safe_feed(sc, re);
++	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
++	return (0);
++
++errout:
++	if (re->re_src.map != re->re_dst.map)
++		pci_unmap_operand(sc, &re->re_dst);
++	if (re->re_src.map)
++		pci_unmap_operand(sc, &re->re_src);
++	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
++	if (err != ERESTART) {
++		crp->crp_etype = err;
++		crypto_done(crp);
++	} else {
++		sc->sc_needwakeup |= CRYPTO_SYMQ;
++	}
++	return (err);
++}
++
++static void
++safe_callback(struct safe_softc *sc, struct safe_ringentry *re)
++{
++	struct cryptop *crp = (struct cryptop *)re->re_crp;
++	struct cryptodesc *crd;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	safestats.st_opackets++;
++	safestats.st_obytes += re->re_dst.mapsize;
++
++	if (re->re_desc.d_csr & SAFE_PE_CSR_STATUS) {
++		device_printf(sc->sc_dev, "csr 0x%x cmd0 0x%x cmd1 0x%x\n",
++			re->re_desc.d_csr,
++			re->re_sa.sa_cmd0, re->re_sa.sa_cmd1);
++		safestats.st_peoperr++;
++		crp->crp_etype = EIO;		/* something more meaningful? */
++	}
++
++	if (re->re_dst.map != NULL && re->re_dst.map != re->re_src.map)
++		pci_unmap_operand(sc, &re->re_dst);
++	pci_unmap_operand(sc, &re->re_src);
++
++	/* 
++	 * If result was written to a differet mbuf chain, swap
++	 * it in as the return value and reclaim the original.
++	 */
++	if ((crp->crp_flags & CRYPTO_F_SKBUF) && re->re_src_skb != re->re_dst_skb) {
++		device_printf(sc->sc_dev, "no CRYPTO_F_SKBUF swapping support\n");
++		/* kfree_skb(skb) */
++		/* crp->crp_buf = (caddr_t)re->re_dst_skb */
++		return;
++	}
++
++	if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) {
++		/* copy out IV for future use */
++		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
++			int i;
++			int ivsize;
++
++			if (crd->crd_alg == CRYPTO_DES_CBC ||
++			    crd->crd_alg == CRYPTO_3DES_CBC) {
++				ivsize = 2*sizeof(u_int32_t);
++			} else if (crd->crd_alg == CRYPTO_AES_CBC) {
++				ivsize = 4*sizeof(u_int32_t);
++			} else
++				continue;
++			crypto_copydata(crp->crp_flags, crp->crp_buf,
++			    crd->crd_skip + crd->crd_len - ivsize, ivsize,
++			    (caddr_t)sc->sc_sessions[re->re_sesn].ses_iv);
++			for (i = 0;
++					i < ivsize/sizeof(sc->sc_sessions[re->re_sesn].ses_iv[0]);
++					i++)
++				sc->sc_sessions[re->re_sesn].ses_iv[i] =
++					cpu_to_le32(sc->sc_sessions[re->re_sesn].ses_iv[i]);
++			break;
++		}
++	}
++
++	if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) {
++		/* copy out ICV result */
++		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
++			if (!(crd->crd_alg == CRYPTO_MD5_HMAC ||
++			    crd->crd_alg == CRYPTO_SHA1_HMAC ||
++			    crd->crd_alg == CRYPTO_NULL_HMAC))
++				continue;
++			if (crd->crd_alg == CRYPTO_SHA1_HMAC) {
++				/*
++				 * SHA-1 ICV's are byte-swapped; fix 'em up
++				 * before copy them to their destination.
++				 */
++				re->re_sastate.sa_saved_indigest[0] =
++					cpu_to_be32(re->re_sastate.sa_saved_indigest[0]);
++				re->re_sastate.sa_saved_indigest[1] = 
++					cpu_to_be32(re->re_sastate.sa_saved_indigest[1]);
++				re->re_sastate.sa_saved_indigest[2] =
++					cpu_to_be32(re->re_sastate.sa_saved_indigest[2]);
++			} else {
++				re->re_sastate.sa_saved_indigest[0] =
++					cpu_to_le32(re->re_sastate.sa_saved_indigest[0]);
++				re->re_sastate.sa_saved_indigest[1] = 
++					cpu_to_le32(re->re_sastate.sa_saved_indigest[1]);
++				re->re_sastate.sa_saved_indigest[2] =
++					cpu_to_le32(re->re_sastate.sa_saved_indigest[2]);
++			}
++			crypto_copyback(crp->crp_flags, crp->crp_buf,
++			    crd->crd_inject,
++			    sc->sc_sessions[re->re_sesn].ses_mlen,
++			    (caddr_t)re->re_sastate.sa_saved_indigest);
++			break;
++		}
++	}
++	crypto_done(crp);
++}
++
++
++#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
++#define	SAFE_RNG_MAXWAIT	1000
++
++static void
++safe_rng_init(struct safe_softc *sc)
++{
++	u_int32_t w, v;
++	int i;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	WRITE_REG(sc, SAFE_RNG_CTRL, 0);
++	/* use default value according to the manual */
++	WRITE_REG(sc, SAFE_RNG_CNFG, 0x834);	/* magic from SafeNet */
++	WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
++
++	/*
++	 * There is a bug in rev 1.0 of the 1140 that when the RNG
++	 * is brought out of reset the ready status flag does not
++	 * work until the RNG has finished its internal initialization.
++	 *
++	 * So in order to determine the device is through its
++	 * initialization we must read the data register, using the
++	 * status reg in the read in case it is initialized.  Then read
++	 * the data register until it changes from the first read.
++	 * Once it changes read the data register until it changes
++	 * again.  At this time the RNG is considered initialized. 
++	 * This could take between 750ms - 1000ms in time.
++	 */
++	i = 0;
++	w = READ_REG(sc, SAFE_RNG_OUT);
++	do {
++		v = READ_REG(sc, SAFE_RNG_OUT);
++		if (v != w) {
++			w = v;
++			break;
++		}
++		DELAY(10);
++	} while (++i < SAFE_RNG_MAXWAIT);
++
++	/* Wait Until data changes again */
++	i = 0;
++	do {
++		v = READ_REG(sc, SAFE_RNG_OUT);
++		if (v != w)
++			break;
++		DELAY(10);
++	} while (++i < SAFE_RNG_MAXWAIT);
++}
++
++static __inline void
++safe_rng_disable_short_cycle(struct safe_softc *sc)
++{
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	WRITE_REG(sc, SAFE_RNG_CTRL,
++		READ_REG(sc, SAFE_RNG_CTRL) &~ SAFE_RNG_CTRL_SHORTEN);
++}
++
++static __inline void
++safe_rng_enable_short_cycle(struct safe_softc *sc)
++{
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	WRITE_REG(sc, SAFE_RNG_CTRL, 
++		READ_REG(sc, SAFE_RNG_CTRL) | SAFE_RNG_CTRL_SHORTEN);
++}
++
++static __inline u_int32_t
++safe_rng_read(struct safe_softc *sc)
++{
++	int i;
++
++	i = 0;
++	while (READ_REG(sc, SAFE_RNG_STAT) != 0 && ++i < SAFE_RNG_MAXWAIT)
++		;
++	return READ_REG(sc, SAFE_RNG_OUT);
++}
++
++static int
++safe_read_random(void *arg, u_int32_t *buf, int maxwords)
++{
++	struct safe_softc *sc = (struct safe_softc *) arg;
++	int i, rc;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++	
++	safestats.st_rng++;
++	/*
++	 * Fetch the next block of data.
++	 */
++	if (maxwords > safe_rngbufsize)
++		maxwords = safe_rngbufsize;
++	if (maxwords > SAFE_RNG_MAXBUFSIZ)
++		maxwords = SAFE_RNG_MAXBUFSIZ;
++retry:
++	/* read as much as we can */
++	for (rc = 0; rc < maxwords; rc++) {
++		if (READ_REG(sc, SAFE_RNG_STAT) != 0)
++			break;
++		buf[rc] = READ_REG(sc, SAFE_RNG_OUT);
++	}
++	if (rc == 0)
++		return 0;
++	/*
++	 * Check the comparator alarm count and reset the h/w if
++	 * it exceeds our threshold.  This guards against the
++	 * hardware oscillators resonating with external signals.
++	 */
++	if (READ_REG(sc, SAFE_RNG_ALM_CNT) > safe_rngmaxalarm) {
++		u_int32_t freq_inc, w;
++
++		DPRINTF(("%s: alarm count %u exceeds threshold %u\n", __func__,
++			(unsigned)READ_REG(sc, SAFE_RNG_ALM_CNT), safe_rngmaxalarm));
++		safestats.st_rngalarm++;
++		safe_rng_enable_short_cycle(sc);
++		freq_inc = 18;
++		for (i = 0; i < 64; i++) {
++			w = READ_REG(sc, SAFE_RNG_CNFG);
++			freq_inc = ((w + freq_inc) & 0x3fL);
++			w = ((w & ~0x3fL) | freq_inc);
++			WRITE_REG(sc, SAFE_RNG_CNFG, w);
++
++			WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
++
++			(void) safe_rng_read(sc);
++			DELAY(25);
++
++			if (READ_REG(sc, SAFE_RNG_ALM_CNT) == 0) {
++				safe_rng_disable_short_cycle(sc);
++				goto retry;
++			}
++			freq_inc = 1;
++		}
++		safe_rng_disable_short_cycle(sc);
++	} else
++		WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
++
++	return(rc);
++}
++#endif /* defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG) */
++
++
++/*
++ * Resets the board.  Values in the regesters are left as is
++ * from the reset (i.e. initial values are assigned elsewhere).
++ */
++static void
++safe_reset_board(struct safe_softc *sc)
++{
++	u_int32_t v;
++	/*
++	 * Reset the device.  The manual says no delay
++	 * is needed between marking and clearing reset.
++	 */
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	v = READ_REG(sc, SAFE_PE_DMACFG) &~
++		(SAFE_PE_DMACFG_PERESET | SAFE_PE_DMACFG_PDRRESET |
++		 SAFE_PE_DMACFG_SGRESET);
++	WRITE_REG(sc, SAFE_PE_DMACFG, v
++				    | SAFE_PE_DMACFG_PERESET
++				    | SAFE_PE_DMACFG_PDRRESET
++				    | SAFE_PE_DMACFG_SGRESET);
++	WRITE_REG(sc, SAFE_PE_DMACFG, v);
++}
++
++/*
++ * Initialize registers we need to touch only once.
++ */
++static void
++safe_init_board(struct safe_softc *sc)
++{
++	u_int32_t v, dwords;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	v = READ_REG(sc, SAFE_PE_DMACFG);
++	v &=~ (   SAFE_PE_DMACFG_PEMODE
++			| SAFE_PE_DMACFG_FSENA		/* failsafe enable */
++			| SAFE_PE_DMACFG_GPRPCI		/* gather ring on PCI */
++			| SAFE_PE_DMACFG_SPRPCI		/* scatter ring on PCI */
++			| SAFE_PE_DMACFG_ESDESC		/* endian-swap descriptors */
++			| SAFE_PE_DMACFG_ESPDESC	/* endian-swap part. desc's */
++			| SAFE_PE_DMACFG_ESSA		/* endian-swap SA's */
++			| SAFE_PE_DMACFG_ESPACKET	/* swap the packet data */
++		  );
++	v |= SAFE_PE_DMACFG_FSENA		/* failsafe enable */
++	  |  SAFE_PE_DMACFG_GPRPCI		/* gather ring on PCI */
++	  |  SAFE_PE_DMACFG_SPRPCI		/* scatter ring on PCI */
++	  |  SAFE_PE_DMACFG_ESDESC		/* endian-swap descriptors */
++	  |  SAFE_PE_DMACFG_ESPDESC		/* endian-swap part. desc's */
++	  |  SAFE_PE_DMACFG_ESSA		/* endian-swap SA's */
++#if 0
++	  |  SAFE_PE_DMACFG_ESPACKET    /* swap the packet data */
++#endif
++	  ;
++	WRITE_REG(sc, SAFE_PE_DMACFG, v);
++
++#ifdef __BIG_ENDIAN
++	/* tell the safenet that we are 4321 and not 1234 */
++	WRITE_REG(sc, SAFE_ENDIAN, 0xe4e41b1b);
++#endif
++
++	if (sc->sc_chiprev == SAFE_REV(1,0)) {
++		/*
++		 * Avoid large PCI DMA transfers.  Rev 1.0 has a bug where
++		 * "target mode transfers" done while the chip is DMA'ing
++		 * >1020 bytes cause the hardware to lockup.  To avoid this
++		 * we reduce the max PCI transfer size and use small source
++		 * particle descriptors (<= 256 bytes).
++		 */
++		WRITE_REG(sc, SAFE_DMA_CFG, 256);
++		device_printf(sc->sc_dev,
++			"Reduce max DMA size to %u words for rev %u.%u WAR\n",
++			(unsigned) ((READ_REG(sc, SAFE_DMA_CFG)>>2) & 0xff),
++			(unsigned) SAFE_REV_MAJ(sc->sc_chiprev),
++			(unsigned) SAFE_REV_MIN(sc->sc_chiprev));
++		sc->sc_max_dsize = 256;
++	} else {
++		sc->sc_max_dsize = SAFE_MAX_DSIZE;
++	}
++
++	/* NB: operands+results are overlaid */
++	WRITE_REG(sc, SAFE_PE_PDRBASE, sc->sc_ringalloc.dma_paddr);
++	WRITE_REG(sc, SAFE_PE_RDRBASE, sc->sc_ringalloc.dma_paddr);
++	/*
++	 * Configure ring entry size and number of items in the ring.
++	 */
++	KASSERT((sizeof(struct safe_ringentry) % sizeof(u_int32_t)) == 0,
++		("PE ring entry not 32-bit aligned!"));
++	dwords = sizeof(struct safe_ringentry) / sizeof(u_int32_t);
++	WRITE_REG(sc, SAFE_PE_RINGCFG,
++		(dwords << SAFE_PE_RINGCFG_OFFSET_S) | SAFE_MAX_NQUEUE);
++	WRITE_REG(sc, SAFE_PE_RINGPOLL, 0);	/* disable polling */
++
++	WRITE_REG(sc, SAFE_PE_GRNGBASE, sc->sc_spalloc.dma_paddr);
++	WRITE_REG(sc, SAFE_PE_SRNGBASE, sc->sc_dpalloc.dma_paddr);
++	WRITE_REG(sc, SAFE_PE_PARTSIZE,
++		(SAFE_TOTAL_DPART<<16) | SAFE_TOTAL_SPART);
++	/*
++	 * NB: destination particles are fixed size.  We use
++	 *     an mbuf cluster and require all results go to
++	 *     clusters or smaller.
++	 */
++	WRITE_REG(sc, SAFE_PE_PARTCFG, sc->sc_max_dsize);
++
++	/* it's now safe to enable PE mode, do it */
++	WRITE_REG(sc, SAFE_PE_DMACFG, v | SAFE_PE_DMACFG_PEMODE);
++
++	/*
++	 * Configure hardware to use level-triggered interrupts and
++	 * to interrupt after each descriptor is processed.
++	 */
++	WRITE_REG(sc, SAFE_HI_CFG, SAFE_HI_CFG_LEVEL);
++	WRITE_REG(sc, SAFE_HI_CLR, 0xffffffff);
++	WRITE_REG(sc, SAFE_HI_DESC_CNT, 1);
++	WRITE_REG(sc, SAFE_HI_MASK, SAFE_INT_PE_DDONE | SAFE_INT_PE_ERROR);
++}
++
++
++/*
++ * Clean up after a chip crash.
++ * It is assumed that the caller in splimp()
++ */
++static void
++safe_cleanchip(struct safe_softc *sc)
++{
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (sc->sc_nqchip != 0) {
++		struct safe_ringentry *re = sc->sc_back;
++
++		while (re != sc->sc_front) {
++			if (re->re_desc.d_csr != 0)
++				safe_free_entry(sc, re);
++			if (++re == sc->sc_ringtop)
++				re = sc->sc_ring;
++		}
++		sc->sc_back = re;
++		sc->sc_nqchip = 0;
++	}
++}
++
++/*
++ * free a safe_q
++ * It is assumed that the caller is within splimp().
++ */
++static int
++safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re)
++{
++	struct cryptop *crp;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	/*
++	 * Free header MCR
++	 */
++	if ((re->re_dst_skb != NULL) && (re->re_src_skb != re->re_dst_skb))
++#ifdef NOTYET
++		m_freem(re->re_dst_m);
++#else
++		printk("%s,%d: SKB not supported\n", __FILE__, __LINE__);
++#endif
++
++	crp = (struct cryptop *)re->re_crp;
++	
++	re->re_desc.d_csr = 0;
++	
++	crp->crp_etype = EFAULT;
++	crypto_done(crp);
++	return(0);
++}
++
++/*
++ * Routine to reset the chip and clean up.
++ * It is assumed that the caller is in splimp()
++ */
++static void
++safe_totalreset(struct safe_softc *sc)
++{
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	safe_reset_board(sc);
++	safe_init_board(sc);
++	safe_cleanchip(sc);
++}
++
++/*
++ * Is the operand suitable aligned for direct DMA.  Each
++ * segment must be aligned on a 32-bit boundary and all
++ * but the last segment must be a multiple of 4 bytes.
++ */
++static int
++safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op)
++{
++	int i;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	for (i = 0; i < op->nsegs; i++) {
++		if (op->segs[i].ds_addr & 3)
++			return (0);
++		if (i != (op->nsegs - 1) && (op->segs[i].ds_len & 3))
++			return (0);
++	}
++	return (1);
++}
++
++/*
++ * Is the operand suitable for direct DMA as the destination
++ * of an operation.  The hardware requires that each ``particle''
++ * but the last in an operation result have the same size.  We
++ * fix that size at SAFE_MAX_DSIZE bytes.  This routine returns
++ * 0 if some segment is not a multiple of of this size, 1 if all
++ * segments are exactly this size, or 2 if segments are at worst
++ * a multple of this size.
++ */
++static int
++safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op)
++{
++	int result = 1;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (op->nsegs > 0) {
++		int i;
++
++		for (i = 0; i < op->nsegs-1; i++) {
++			if (op->segs[i].ds_len % sc->sc_max_dsize)
++				return (0);
++			if (op->segs[i].ds_len != sc->sc_max_dsize)
++				result = 2;
++		}
++	}
++	return (result);
++}
++
++static int
++safe_kprocess(device_t dev, struct cryptkop *krp, int hint)
++{
++	struct safe_softc *sc = device_get_softc(dev);
++	struct safe_pkq *q;
++	unsigned long flags;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (sc == NULL) {
++		krp->krp_status = EINVAL;
++		goto err;
++	}
++
++	if (krp->krp_op != CRK_MOD_EXP) {
++		krp->krp_status = EOPNOTSUPP;
++		goto err;
++	}
++
++	q = (struct safe_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
++	if (q == NULL) {
++		krp->krp_status = ENOMEM;
++		goto err;
++	}
++	memset(q, 0, sizeof(*q));
++	q->pkq_krp = krp;
++	INIT_LIST_HEAD(&q->pkq_list);
++
++	spin_lock_irqsave(&sc->sc_pkmtx, flags);
++	list_add_tail(&q->pkq_list, &sc->sc_pkq);
++	safe_kfeed(sc);
++	spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
++	return (0);
++
++err:
++	crypto_kdone(krp);
++	return (0);
++}
++
++#define	SAFE_CRK_PARAM_BASE	0
++#define	SAFE_CRK_PARAM_EXP	1
++#define	SAFE_CRK_PARAM_MOD	2
++
++static int
++safe_kstart(struct safe_softc *sc)
++{
++	struct cryptkop *krp = sc->sc_pkq_cur->pkq_krp;
++	int exp_bits, mod_bits, base_bits;
++	u_int32_t op, a_off, b_off, c_off, d_off;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (krp->krp_iparams < 3 || krp->krp_oparams != 1) {
++		krp->krp_status = EINVAL;
++		return (1);
++	}
++
++	base_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_BASE]);
++	if (base_bits > 2048)
++		goto too_big;
++	if (base_bits <= 0)		/* 5. base not zero */
++		goto too_small;
++
++	exp_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_EXP]);
++	if (exp_bits > 2048)
++		goto too_big;
++	if (exp_bits <= 0)		/* 1. exponent word length > 0 */
++		goto too_small;		/* 4. exponent not zero */
++
++	mod_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_MOD]);
++	if (mod_bits > 2048)
++		goto too_big;
++	if (mod_bits <= 32)		/* 2. modulus word length > 1 */
++		goto too_small;		/* 8. MSW of modulus != zero */
++	if (mod_bits < exp_bits)	/* 3 modulus len >= exponent len */
++		goto too_small;
++	if ((krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p[0] & 1) == 0)
++		goto bad_domain;	/* 6. modulus is odd */
++	if (mod_bits > krp->krp_param[krp->krp_iparams].crp_nbits)
++		goto too_small;		/* make sure result will fit */
++
++	/* 7. modulus > base */
++	if (mod_bits < base_bits)
++		goto too_small;
++	if (mod_bits == base_bits) {
++		u_int8_t *basep, *modp;
++		int i;
++
++		basep = krp->krp_param[SAFE_CRK_PARAM_BASE].crp_p +
++		    ((base_bits + 7) / 8) - 1;
++		modp = krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p +
++		    ((mod_bits + 7) / 8) - 1;
++		
++		for (i = 0; i < (mod_bits + 7) / 8; i++, basep--, modp--) {
++			if (*modp < *basep)
++				goto too_small;
++			if (*modp > *basep)
++				break;
++		}
++	}
++
++	/* And on the 9th step, he rested. */
++
++	WRITE_REG(sc, SAFE_PK_A_LEN, (exp_bits + 31) / 32);
++	WRITE_REG(sc, SAFE_PK_B_LEN, (mod_bits + 31) / 32);
++	if (mod_bits > 1024) {
++		op = SAFE_PK_FUNC_EXP4;
++		a_off = 0x000;
++		b_off = 0x100;
++		c_off = 0x200;
++		d_off = 0x300;
++	} else {
++		op = SAFE_PK_FUNC_EXP16;
++		a_off = 0x000;
++		b_off = 0x080;
++		c_off = 0x100;
++		d_off = 0x180;
++	}
++	sc->sc_pk_reslen = b_off - a_off;
++	sc->sc_pk_resoff = d_off;
++
++	/* A is exponent, B is modulus, C is base, D is result */
++	safe_kload_reg(sc, a_off, b_off - a_off,
++	    &krp->krp_param[SAFE_CRK_PARAM_EXP]);
++	WRITE_REG(sc, SAFE_PK_A_ADDR, a_off >> 2);
++	safe_kload_reg(sc, b_off, b_off - a_off,
++	    &krp->krp_param[SAFE_CRK_PARAM_MOD]);
++	WRITE_REG(sc, SAFE_PK_B_ADDR, b_off >> 2);
++	safe_kload_reg(sc, c_off, b_off - a_off,
++	    &krp->krp_param[SAFE_CRK_PARAM_BASE]);
++	WRITE_REG(sc, SAFE_PK_C_ADDR, c_off >> 2);
++	WRITE_REG(sc, SAFE_PK_D_ADDR, d_off >> 2);
++
++	WRITE_REG(sc, SAFE_PK_FUNC, op | SAFE_PK_FUNC_RUN);
++
++	return (0);
++
++too_big:
++	krp->krp_status = E2BIG;
++	return (1);
++too_small:
++	krp->krp_status = ERANGE;
++	return (1);
++bad_domain:
++	krp->krp_status = EDOM;
++	return (1);
++}
++
++static int
++safe_ksigbits(struct safe_softc *sc, struct crparam *cr)
++{
++	u_int plen = (cr->crp_nbits + 7) / 8;
++	int i, sig = plen * 8;
++	u_int8_t c, *p = cr->crp_p;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	for (i = plen - 1; i >= 0; i--) {
++		c = p[i];
++		if (c != 0) {
++			while ((c & 0x80) == 0) {
++				sig--;
++				c <<= 1;
++			}
++			break;
++		}
++		sig -= 8;
++	}
++	return (sig);
++}
++
++static void
++safe_kfeed(struct safe_softc *sc)
++{
++	struct safe_pkq *q, *tmp;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (list_empty(&sc->sc_pkq) && sc->sc_pkq_cur == NULL)
++		return;
++	if (sc->sc_pkq_cur != NULL)
++		return;
++	list_for_each_entry_safe(q, tmp, &sc->sc_pkq, pkq_list) {
++		sc->sc_pkq_cur = q;
++		list_del(&q->pkq_list);
++		if (safe_kstart(sc) != 0) {
++			crypto_kdone(q->pkq_krp);
++			kfree(q);
++			sc->sc_pkq_cur = NULL;
++		} else {
++			/* op started, start polling */
++			mod_timer(&sc->sc_pkto, jiffies + 1);
++			break;
++		}
++	}
++}
++
++static void
++safe_kpoll(unsigned long arg)
++{
++	struct safe_softc *sc = NULL;
++	struct safe_pkq *q;
++	struct crparam *res;
++	int i;
++	u_int32_t buf[64];
++	unsigned long flags;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (arg >= SAFE_MAX_CHIPS)
++		return;
++	sc = safe_chip_idx[arg];
++	if (!sc) {
++		DPRINTF(("%s() - bad callback\n", __FUNCTION__));
++		return;
++	}
++
++	spin_lock_irqsave(&sc->sc_pkmtx, flags);
++	if (sc->sc_pkq_cur == NULL)
++		goto out;
++	if (READ_REG(sc, SAFE_PK_FUNC) & SAFE_PK_FUNC_RUN) {
++		/* still running, check back later */
++		mod_timer(&sc->sc_pkto, jiffies + 1);
++		goto out;
++	}
++
++	q = sc->sc_pkq_cur;
++	res = &q->pkq_krp->krp_param[q->pkq_krp->krp_iparams];
++	bzero(buf, sizeof(buf));
++	bzero(res->crp_p, (res->crp_nbits + 7) / 8);
++	for (i = 0; i < sc->sc_pk_reslen >> 2; i++)
++		buf[i] = le32_to_cpu(READ_REG(sc, SAFE_PK_RAM_START +
++		    sc->sc_pk_resoff + (i << 2)));
++	bcopy(buf, res->crp_p, (res->crp_nbits + 7) / 8);
++	/*
++	 * reduce the bits that need copying if possible
++	 */
++	res->crp_nbits = min(res->crp_nbits,sc->sc_pk_reslen * 8);
++	res->crp_nbits = safe_ksigbits(sc, res);
++
++	for (i = SAFE_PK_RAM_START; i < SAFE_PK_RAM_END; i += 4)
++		WRITE_REG(sc, i, 0);
++
++	crypto_kdone(q->pkq_krp);
++	kfree(q);
++	sc->sc_pkq_cur = NULL;
++
++	safe_kfeed(sc);
++out:
++	spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
++}
++
++static void
++safe_kload_reg(struct safe_softc *sc, u_int32_t off, u_int32_t len,
++    struct crparam *n)
++{
++	u_int32_t buf[64], i;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	bzero(buf, sizeof(buf));
++	bcopy(n->crp_p, buf, (n->crp_nbits + 7) / 8);
++
++	for (i = 0; i < len >> 2; i++)
++		WRITE_REG(sc, SAFE_PK_RAM_START + off + (i << 2),
++		    cpu_to_le32(buf[i]));
++}
++
++#ifdef SAFE_DEBUG
++static void
++safe_dump_dmastatus(struct safe_softc *sc, const char *tag)
++{
++	printf("%s: ENDIAN 0x%x SRC 0x%x DST 0x%x STAT 0x%x\n"
++		, tag
++		, READ_REG(sc, SAFE_DMA_ENDIAN)
++		, READ_REG(sc, SAFE_DMA_SRCADDR)
++		, READ_REG(sc, SAFE_DMA_DSTADDR)
++		, READ_REG(sc, SAFE_DMA_STAT)
++	);
++}
++
++static void
++safe_dump_intrstate(struct safe_softc *sc, const char *tag)
++{
++	printf("%s: HI_CFG 0x%x HI_MASK 0x%x HI_DESC_CNT 0x%x HU_STAT 0x%x HM_STAT 0x%x\n"
++		, tag
++		, READ_REG(sc, SAFE_HI_CFG)
++		, READ_REG(sc, SAFE_HI_MASK)
++		, READ_REG(sc, SAFE_HI_DESC_CNT)
++		, READ_REG(sc, SAFE_HU_STAT)
++		, READ_REG(sc, SAFE_HM_STAT)
++	);
++}
++
++static void
++safe_dump_ringstate(struct safe_softc *sc, const char *tag)
++{
++	u_int32_t estat = READ_REG(sc, SAFE_PE_ERNGSTAT);
++
++	/* NB: assume caller has lock on ring */
++	printf("%s: ERNGSTAT %x (next %u) back %lu front %lu\n",
++		tag,
++		estat, (estat >> SAFE_PE_ERNGSTAT_NEXT_S),
++		(unsigned long)(sc->sc_back - sc->sc_ring),
++		(unsigned long)(sc->sc_front - sc->sc_ring));
++}
++
++static void
++safe_dump_request(struct safe_softc *sc, const char* tag, struct safe_ringentry *re)
++{
++	int ix, nsegs;
++
++	ix = re - sc->sc_ring;
++	printf("%s: %p (%u): csr %x src %x dst %x sa %x len %x\n"
++		, tag
++		, re, ix
++		, re->re_desc.d_csr
++		, re->re_desc.d_src
++		, re->re_desc.d_dst
++		, re->re_desc.d_sa
++		, re->re_desc.d_len
++	);
++	if (re->re_src.nsegs > 1) {
++		ix = (re->re_desc.d_src - sc->sc_spalloc.dma_paddr) /
++			sizeof(struct safe_pdesc);
++		for (nsegs = re->re_src.nsegs; nsegs; nsegs--) {
++			printf(" spd[%u] %p: %p size %u flags %x"
++				, ix, &sc->sc_spring[ix]
++				, (caddr_t)(uintptr_t) sc->sc_spring[ix].pd_addr
++				, sc->sc_spring[ix].pd_size
++				, sc->sc_spring[ix].pd_flags
++			);
++			if (sc->sc_spring[ix].pd_size == 0)
++				printf(" (zero!)");
++			printf("\n");
++			if (++ix == SAFE_TOTAL_SPART)
++				ix = 0;
++		}
++	}
++	if (re->re_dst.nsegs > 1) {
++		ix = (re->re_desc.d_dst - sc->sc_dpalloc.dma_paddr) /
++			sizeof(struct safe_pdesc);
++		for (nsegs = re->re_dst.nsegs; nsegs; nsegs--) {
++			printf(" dpd[%u] %p: %p flags %x\n"
++				, ix, &sc->sc_dpring[ix]
++				, (caddr_t)(uintptr_t) sc->sc_dpring[ix].pd_addr
++				, sc->sc_dpring[ix].pd_flags
++			);
++			if (++ix == SAFE_TOTAL_DPART)
++				ix = 0;
++		}
++	}
++	printf("sa: cmd0 %08x cmd1 %08x staterec %x\n",
++		re->re_sa.sa_cmd0, re->re_sa.sa_cmd1, re->re_sa.sa_staterec);
++	printf("sa: key %x %x %x %x %x %x %x %x\n"
++		, re->re_sa.sa_key[0]
++		, re->re_sa.sa_key[1]
++		, re->re_sa.sa_key[2]
++		, re->re_sa.sa_key[3]
++		, re->re_sa.sa_key[4]
++		, re->re_sa.sa_key[5]
++		, re->re_sa.sa_key[6]
++		, re->re_sa.sa_key[7]
++	);
++	printf("sa: indigest %x %x %x %x %x\n"
++		, re->re_sa.sa_indigest[0]
++		, re->re_sa.sa_indigest[1]
++		, re->re_sa.sa_indigest[2]
++		, re->re_sa.sa_indigest[3]
++		, re->re_sa.sa_indigest[4]
++	);
++	printf("sa: outdigest %x %x %x %x %x\n"
++		, re->re_sa.sa_outdigest[0]
++		, re->re_sa.sa_outdigest[1]
++		, re->re_sa.sa_outdigest[2]
++		, re->re_sa.sa_outdigest[3]
++		, re->re_sa.sa_outdigest[4]
++	);
++	printf("sr: iv %x %x %x %x\n"
++		, re->re_sastate.sa_saved_iv[0]
++		, re->re_sastate.sa_saved_iv[1]
++		, re->re_sastate.sa_saved_iv[2]
++		, re->re_sastate.sa_saved_iv[3]
++	);
++	printf("sr: hashbc %u indigest %x %x %x %x %x\n"
++		, re->re_sastate.sa_saved_hashbc
++		, re->re_sastate.sa_saved_indigest[0]
++		, re->re_sastate.sa_saved_indigest[1]
++		, re->re_sastate.sa_saved_indigest[2]
++		, re->re_sastate.sa_saved_indigest[3]
++		, re->re_sastate.sa_saved_indigest[4]
++	);
++}
++
++static void
++safe_dump_ring(struct safe_softc *sc, const char *tag)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&sc->sc_ringmtx, flags);
++	printf("\nSafeNet Ring State:\n");
++	safe_dump_intrstate(sc, tag);
++	safe_dump_dmastatus(sc, tag);
++	safe_dump_ringstate(sc, tag);
++	if (sc->sc_nqchip) {
++		struct safe_ringentry *re = sc->sc_back;
++		do {
++			safe_dump_request(sc, tag, re);
++			if (++re == sc->sc_ringtop)
++				re = sc->sc_ring;
++		} while (re != sc->sc_front);
++	}
++	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
++}
++#endif /* SAFE_DEBUG */
++
++
++static int safe_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++{
++	struct safe_softc *sc = NULL;
++	u32 mem_start, mem_len, cmd;
++	int i, rc, devinfo;
++	dma_addr_t raddr;
++	static int num_chips = 0;
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	if (pci_enable_device(dev) < 0)
++		return(-ENODEV);
++
++	if (!dev->irq) {
++		printk("safe: found device with no IRQ assigned. check BIOS settings!");
++		pci_disable_device(dev);
++		return(-ENODEV);
++	}
++
++	if (pci_set_mwi(dev)) {
++		printk("safe: pci_set_mwi failed!");
++		return(-ENODEV);
++	}
++
++	sc = (struct safe_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
++	if (!sc)
++		return(-ENOMEM);
++	memset(sc, 0, sizeof(*sc));
++
++	softc_device_init(sc, "safe", num_chips, safe_methods);
++
++	sc->sc_irq = -1;
++	sc->sc_cid = -1;
++	sc->sc_pcidev = dev;
++	if (num_chips < SAFE_MAX_CHIPS) {
++		safe_chip_idx[device_get_unit(sc->sc_dev)] = sc;
++		num_chips++;
++	}
++
++	INIT_LIST_HEAD(&sc->sc_pkq);
++	spin_lock_init(&sc->sc_pkmtx);
++
++	pci_set_drvdata(sc->sc_pcidev, sc);
++
++	/* we read its hardware registers as memory */
++	mem_start = pci_resource_start(sc->sc_pcidev, 0);
++	mem_len   = pci_resource_len(sc->sc_pcidev, 0);
++
++	sc->sc_base_addr = (ocf_iomem_t) ioremap(mem_start, mem_len);
++	if (!sc->sc_base_addr) {
++		device_printf(sc->sc_dev, "failed to ioremap 0x%x-0x%x\n",
++				mem_start, mem_start + mem_len - 1);
++		goto out;
++	}
++
++	/* fix up the bus size */
++	if (pci_set_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
++		device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
++		goto out;
++	}
++	if (pci_set_consistent_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
++		device_printf(sc->sc_dev, "No usable consistent DMA configuration, aborting.\n");
++		goto out;
++	}
++
++	pci_set_master(sc->sc_pcidev);
++
++	pci_read_config_dword(sc->sc_pcidev, PCI_COMMAND, &cmd);
++
++	if (!(cmd & PCI_COMMAND_MEMORY)) {
++		device_printf(sc->sc_dev, "failed to enable memory mapping\n");
++		goto out;
++	}
++
++	if (!(cmd & PCI_COMMAND_MASTER)) {
++		device_printf(sc->sc_dev, "failed to enable bus mastering\n");
++		goto out;
++	}
++
++	rc = request_irq(dev->irq, safe_intr, IRQF_SHARED, "safe", sc);
++	if (rc) {
++		device_printf(sc->sc_dev, "failed to hook irq %d\n", sc->sc_irq);
++		goto out;
++	}
++	sc->sc_irq = dev->irq;
++
++	sc->sc_chiprev = READ_REG(sc, SAFE_DEVINFO) &
++			(SAFE_DEVINFO_REV_MAJ | SAFE_DEVINFO_REV_MIN);
++
++	/*
++	 * Allocate packet engine descriptors.
++	 */
++	sc->sc_ringalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
++			SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
++			&sc->sc_ringalloc.dma_paddr);
++	if (!sc->sc_ringalloc.dma_vaddr) {
++		device_printf(sc->sc_dev, "cannot allocate PE descriptor ring\n");
++		goto out;
++	}
++
++	/*
++	 * Hookup the static portion of all our data structures.
++	 */
++	sc->sc_ring = (struct safe_ringentry *) sc->sc_ringalloc.dma_vaddr;
++	sc->sc_ringtop = sc->sc_ring + SAFE_MAX_NQUEUE;
++	sc->sc_front = sc->sc_ring;
++	sc->sc_back = sc->sc_ring;
++	raddr = sc->sc_ringalloc.dma_paddr;
++	bzero(sc->sc_ring, SAFE_MAX_NQUEUE * sizeof(struct safe_ringentry));
++	for (i = 0; i < SAFE_MAX_NQUEUE; i++) {
++		struct safe_ringentry *re = &sc->sc_ring[i];
++
++		re->re_desc.d_sa = raddr +
++			offsetof(struct safe_ringentry, re_sa);
++		re->re_sa.sa_staterec = raddr +
++			offsetof(struct safe_ringentry, re_sastate);
++
++		raddr += sizeof (struct safe_ringentry);
++	}
++	spin_lock_init(&sc->sc_ringmtx);
++
++	/*
++	 * Allocate scatter and gather particle descriptors.
++	 */
++	sc->sc_spalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
++			SAFE_TOTAL_SPART * sizeof (struct safe_pdesc),
++			&sc->sc_spalloc.dma_paddr);
++	if (!sc->sc_spalloc.dma_vaddr) {
++		device_printf(sc->sc_dev, "cannot allocate source particle descriptor ring\n");
++		goto out;
++	}
++	sc->sc_spring = (struct safe_pdesc *) sc->sc_spalloc.dma_vaddr;
++	sc->sc_springtop = sc->sc_spring + SAFE_TOTAL_SPART;
++	sc->sc_spfree = sc->sc_spring;
++	bzero(sc->sc_spring, SAFE_TOTAL_SPART * sizeof(struct safe_pdesc));
++
++	sc->sc_dpalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
++			SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
++			&sc->sc_dpalloc.dma_paddr);
++	if (!sc->sc_dpalloc.dma_vaddr) {
++		device_printf(sc->sc_dev, "cannot allocate destination particle descriptor ring\n");
++		goto out;
++	}
++	sc->sc_dpring = (struct safe_pdesc *) sc->sc_dpalloc.dma_vaddr;
++	sc->sc_dpringtop = sc->sc_dpring + SAFE_TOTAL_DPART;
++	sc->sc_dpfree = sc->sc_dpring;
++	bzero(sc->sc_dpring, SAFE_TOTAL_DPART * sizeof(struct safe_pdesc));
++
++	sc->sc_cid = crypto_get_driverid(softc_get_device(sc), CRYPTOCAP_F_HARDWARE);
++	if (sc->sc_cid < 0) {
++		device_printf(sc->sc_dev, "could not get crypto driver id\n");
++		goto out;
++	}
++
++	printf("%s:", device_get_nameunit(sc->sc_dev));
++
++	devinfo = READ_REG(sc, SAFE_DEVINFO);
++	if (devinfo & SAFE_DEVINFO_RNG) {
++		sc->sc_flags |= SAFE_FLAGS_RNG;
++		printf(" rng");
++	}
++	if (devinfo & SAFE_DEVINFO_PKEY) {
++		printf(" key");
++		sc->sc_flags |= SAFE_FLAGS_KEY;
++		crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
++#if 0
++		crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
++#endif
++		init_timer(&sc->sc_pkto);
++		sc->sc_pkto.function = safe_kpoll;
++		sc->sc_pkto.data = (unsigned long) device_get_unit(sc->sc_dev);
++	}
++	if (devinfo & SAFE_DEVINFO_DES) {
++		printf(" des/3des");
++		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
++	}
++	if (devinfo & SAFE_DEVINFO_AES) {
++		printf(" aes");
++		crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
++	}
++	if (devinfo & SAFE_DEVINFO_MD5) {
++		printf(" md5");
++		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
++	}
++	if (devinfo & SAFE_DEVINFO_SHA1) {
++		printf(" sha1");
++		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
++	}
++	printf(" null");
++	crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0);
++	crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0);
++	/* XXX other supported algorithms */
++	printf("\n");
++
++	safe_reset_board(sc);		/* reset h/w */
++	safe_init_board(sc);		/* init h/w */
++
++#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
++	if (sc->sc_flags & SAFE_FLAGS_RNG) {
++		safe_rng_init(sc);
++		crypto_rregister(sc->sc_cid, safe_read_random, sc);
++	}
++#endif /* SAFE_NO_RNG */
++
++	return (0);
++
++out:
++	if (sc->sc_cid >= 0)
++		crypto_unregister_all(sc->sc_cid);
++	if (sc->sc_irq != -1)
++		free_irq(sc->sc_irq, sc);
++	if (sc->sc_ringalloc.dma_vaddr)
++		pci_free_consistent(sc->sc_pcidev,
++				SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
++				sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
++	if (sc->sc_spalloc.dma_vaddr)
++		pci_free_consistent(sc->sc_pcidev,
++				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
++				sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
++	if (sc->sc_dpalloc.dma_vaddr)
++		pci_free_consistent(sc->sc_pcidev,
++				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
++				sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
++	kfree(sc);
++	return(-ENODEV);
++}
++
++static void safe_remove(struct pci_dev *dev)
++{
++	struct safe_softc *sc = pci_get_drvdata(dev);
++
++	DPRINTF(("%s()\n", __FUNCTION__));
++
++	/* XXX wait/abort active ops */
++
++	WRITE_REG(sc, SAFE_HI_MASK, 0);		/* disable interrupts */
++
++	del_timer_sync(&sc->sc_pkto);
++
++	crypto_unregister_all(sc->sc_cid);
++
++	safe_cleanchip(sc);
++
++	if (sc->sc_irq != -1)
++		free_irq(sc->sc_irq, sc);
++	if (sc->sc_ringalloc.dma_vaddr)
++		pci_free_consistent(sc->sc_pcidev,
++				SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
++				sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
++	if (sc->sc_spalloc.dma_vaddr)
++		pci_free_consistent(sc->sc_pcidev,
++				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
++				sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
++	if (sc->sc_dpalloc.dma_vaddr)
++		pci_free_consistent(sc->sc_pcidev,
++				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
++				sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
++	sc->sc_irq = -1;
++	sc->sc_ringalloc.dma_vaddr = NULL;
++	sc->sc_spalloc.dma_vaddr = NULL;
++	sc->sc_dpalloc.dma_vaddr = NULL;
++}
++
++static struct pci_device_id safe_pci_tbl[] = {
++	{ PCI_VENDOR_SAFENET, PCI_PRODUCT_SAFEXCEL,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
++	{ },
++};
++MODULE_DEVICE_TABLE(pci, safe_pci_tbl);
++
++static struct pci_driver safe_driver = {
++	.name         = "safe",
++	.id_table     = safe_pci_tbl,
++	.probe        =	safe_probe,
++	.remove       = safe_remove,
++	/* add PM stuff here one day */
++};
++
++static int __init safe_init (void)
++{
++	struct safe_softc *sc = NULL;
++	int rc;
++
++	DPRINTF(("%s(%p)\n", __FUNCTION__, safe_init));
++
++	rc = pci_register_driver(&safe_driver);
++	pci_register_driver_compat(&safe_driver, rc);
++
++	return rc;
++}
++
++static void __exit safe_exit (void)
++{
++	pci_unregister_driver(&safe_driver);
++}
++
++module_init(safe_init);
++module_exit(safe_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
++MODULE_DESCRIPTION("OCF driver for safenet PCI crypto devices");
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/safereg.h linux-2.6.23.16/crypto/ocf/safe/safereg.h
+--- linux-2.6.23.16.old/crypto/ocf/safe/safereg.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/safereg.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,421 @@
++/*-
++ * Copyright (c) 2003 Sam Leffler, Errno Consulting
++ * Copyright (c) 2003 Global Technology Associates, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * $FreeBSD: src/sys/dev/safe/safereg.h,v 1.1 2003/07/21 21:46:07 sam Exp $
++ */
++#ifndef _SAFE_SAFEREG_H_
++#define	_SAFE_SAFEREG_H_
++
++/*
++ * Register definitions for SafeNet SafeXcel-1141 crypto device.
++ * Definitions from revision 1.3 (Nov 6 2002) of the User's Manual.
++ */
++
++#define BS_BAR			0x10	/* DMA base address register */
++#define	BS_TRDY_TIMEOUT		0x40	/* TRDY timeout */
++#define	BS_RETRY_TIMEOUT	0x41	/* DMA retry timeout */
++
++#define	PCI_VENDOR_SAFENET	0x16ae		/* SafeNet, Inc. */
++
++/* SafeNet */
++#define	PCI_PRODUCT_SAFEXCEL	0x1141		/* 1141 */
++
++#define	SAFE_PE_CSR		0x0000	/* Packet Enginge Ctrl/Status */
++#define	SAFE_PE_SRC		0x0004	/* Packet Engine Source */
++#define	SAFE_PE_DST		0x0008	/* Packet Engine Destination */
++#define	SAFE_PE_SA		0x000c	/* Packet Engine SA */
++#define	SAFE_PE_LEN		0x0010	/* Packet Engine Length */
++#define	SAFE_PE_DMACFG		0x0040	/* Packet Engine DMA Configuration */
++#define	SAFE_PE_DMASTAT		0x0044	/* Packet Engine DMA Status */
++#define	SAFE_PE_PDRBASE		0x0048	/* Packet Engine Descriptor Ring Base */
++#define	SAFE_PE_RDRBASE		0x004c	/* Packet Engine Result Ring Base */
++#define	SAFE_PE_RINGCFG		0x0050	/* Packet Engine Ring Configuration */
++#define	SAFE_PE_RINGPOLL	0x0054	/* Packet Engine Ring Poll */
++#define	SAFE_PE_IRNGSTAT	0x0058	/* Packet Engine Internal Ring Status */
++#define	SAFE_PE_ERNGSTAT	0x005c	/* Packet Engine External Ring Status */
++#define	SAFE_PE_IOTHRESH	0x0060	/* Packet Engine I/O Threshold */
++#define	SAFE_PE_GRNGBASE	0x0064	/* Packet Engine Gather Ring Base */
++#define	SAFE_PE_SRNGBASE	0x0068	/* Packet Engine Scatter Ring Base */
++#define	SAFE_PE_PARTSIZE	0x006c	/* Packet Engine Particlar Ring Size */
++#define	SAFE_PE_PARTCFG		0x0070	/* Packet Engine Particle Ring Config */
++#define	SAFE_CRYPTO_CTRL	0x0080	/* Crypto Control */
++#define	SAFE_DEVID		0x0084	/* Device ID */
++#define	SAFE_DEVINFO		0x0088	/* Device Info */
++#define	SAFE_HU_STAT		0x00a0	/* Host Unmasked Status */
++#define	SAFE_HM_STAT		0x00a4	/* Host Masked Status (read-only) */
++#define	SAFE_HI_CLR		0x00a4	/* Host Clear Interrupt (write-only) */
++#define	SAFE_HI_MASK		0x00a8	/* Host Mask Control */
++#define	SAFE_HI_CFG		0x00ac	/* Interrupt Configuration */
++#define	SAFE_HI_RD_DESCR	0x00b4	/* Force Descriptor Read */
++#define	SAFE_HI_DESC_CNT	0x00b8	/* Host Descriptor Done Count */
++#define	SAFE_DMA_ENDIAN		0x00c0	/* Master Endian Status */
++#define	SAFE_DMA_SRCADDR	0x00c4	/* DMA Source Address Status */
++#define	SAFE_DMA_DSTADDR	0x00c8	/* DMA Destination Address Status */
++#define	SAFE_DMA_STAT		0x00cc	/* DMA Current Status */
++#define	SAFE_DMA_CFG		0x00d4	/* DMA Configuration/Status */
++#define	SAFE_ENDIAN		0x00e0	/* Endian Configuration */
++#define	SAFE_PK_A_ADDR		0x0800	/* Public Key A Address */
++#define	SAFE_PK_B_ADDR		0x0804	/* Public Key B Address */
++#define	SAFE_PK_C_ADDR		0x0808	/* Public Key C Address */
++#define	SAFE_PK_D_ADDR		0x080c	/* Public Key D Address */
++#define	SAFE_PK_A_LEN		0x0810	/* Public Key A Length */
++#define	SAFE_PK_B_LEN		0x0814	/* Public Key B Length */
++#define	SAFE_PK_SHIFT		0x0818	/* Public Key Shift */
++#define	SAFE_PK_FUNC		0x081c	/* Public Key Function */
++#define SAFE_PK_RAM_START	0x1000	/* Public Key RAM start address */
++#define SAFE_PK_RAM_END		0x1fff	/* Public Key RAM end address */
++
++#define	SAFE_RNG_OUT		0x0100	/* RNG Output */
++#define	SAFE_RNG_STAT		0x0104	/* RNG Status */
++#define	SAFE_RNG_CTRL		0x0108	/* RNG Control */
++#define	SAFE_RNG_A		0x010c	/* RNG A */
++#define	SAFE_RNG_B		0x0110	/* RNG B */
++#define	SAFE_RNG_X_LO		0x0114	/* RNG X [31:0] */
++#define	SAFE_RNG_X_MID		0x0118	/* RNG X [63:32] */
++#define	SAFE_RNG_X_HI		0x011c	/* RNG X [80:64] */
++#define	SAFE_RNG_X_CNTR		0x0120	/* RNG Counter */
++#define	SAFE_RNG_ALM_CNT	0x0124	/* RNG Alarm Count */
++#define	SAFE_RNG_CNFG		0x0128	/* RNG Configuration */
++#define	SAFE_RNG_LFSR1_LO	0x012c	/* RNG LFSR1 [31:0] */
++#define	SAFE_RNG_LFSR1_HI	0x0130	/* RNG LFSR1 [47:32] */
++#define	SAFE_RNG_LFSR2_LO	0x0134	/* RNG LFSR1 [31:0] */
++#define	SAFE_RNG_LFSR2_HI	0x0138	/* RNG LFSR1 [47:32] */
++
++#define	SAFE_PE_CSR_READY	0x00000001	/* ready for processing */
++#define	SAFE_PE_CSR_DONE	0x00000002	/* h/w completed processing */
++#define	SAFE_PE_CSR_LOADSA	0x00000004	/* load SA digests */
++#define	SAFE_PE_CSR_HASHFINAL	0x00000010	/* do hash pad & write result */
++#define	SAFE_PE_CSR_SABUSID	0x000000c0	/* bus id for SA */
++#define	SAFE_PE_CSR_SAPCI	0x00000040	/* PCI bus id for SA */
++#define	SAFE_PE_CSR_NXTHDR	0x0000ff00	/* next hdr value for IPsec */
++#define	SAFE_PE_CSR_FPAD	0x0000ff00	/* fixed pad for basic ops */
++#define	SAFE_PE_CSR_STATUS	0x00ff0000	/* operation result status */
++#define	SAFE_PE_CSR_AUTH_FAIL	0x00010000	/* ICV mismatch (inbound) */
++#define	SAFE_PE_CSR_PAD_FAIL	0x00020000	/* pad verify fail (inbound) */
++#define	SAFE_PE_CSR_SEQ_FAIL	0x00040000	/* sequence number (inbound) */
++#define	SAFE_PE_CSR_XERROR	0x00080000	/* extended error follows */
++#define	SAFE_PE_CSR_XECODE	0x00f00000	/* extended error code */
++#define	SAFE_PE_CSR_XECODE_S	20
++#define	SAFE_PE_CSR_XECODE_BADCMD	0	/* invalid command */
++#define	SAFE_PE_CSR_XECODE_BADALG	1	/* invalid algorithm */
++#define	SAFE_PE_CSR_XECODE_ALGDIS	2	/* algorithm disabled */
++#define	SAFE_PE_CSR_XECODE_ZEROLEN	3	/* zero packet length */
++#define	SAFE_PE_CSR_XECODE_DMAERR	4	/* bus DMA error */
++#define	SAFE_PE_CSR_XECODE_PIPEABORT	5	/* secondary bus DMA error */
++#define	SAFE_PE_CSR_XECODE_BADSPI	6	/* IPsec SPI mismatch */
++#define	SAFE_PE_CSR_XECODE_TIMEOUT	10	/* failsafe timeout */
++#define	SAFE_PE_CSR_PAD		0xff000000	/* ESP padding control/status */
++#define	SAFE_PE_CSR_PAD_MIN	0x00000000	/* minimum IPsec padding */
++#define	SAFE_PE_CSR_PAD_16	0x08000000	/* pad to 16-byte boundary */
++#define	SAFE_PE_CSR_PAD_32	0x10000000	/* pad to 32-byte boundary */
++#define	SAFE_PE_CSR_PAD_64	0x20000000	/* pad to 64-byte boundary */
++#define	SAFE_PE_CSR_PAD_128	0x40000000	/* pad to 128-byte boundary */
++#define	SAFE_PE_CSR_PAD_256	0x80000000	/* pad to 256-byte boundary */
++
++/*
++ * Check the CSR to see if the PE has returned ownership to
++ * the host.  Note that before processing a descriptor this
++ * must be done followed by a check of the SAFE_PE_LEN register
++ * status bits to avoid premature processing of a descriptor
++ * on its way back to the host.
++ */
++#define	SAFE_PE_CSR_IS_DONE(_csr) \
++    (((_csr) & (SAFE_PE_CSR_READY | SAFE_PE_CSR_DONE)) == SAFE_PE_CSR_DONE)
++
++#define	SAFE_PE_LEN_LENGTH	0x000fffff	/* total length (bytes) */
++#define	SAFE_PE_LEN_READY	0x00400000	/* ready for processing */
++#define	SAFE_PE_LEN_DONE	0x00800000	/* h/w completed processing */
++#define	SAFE_PE_LEN_BYPASS	0xff000000	/* bypass offset (bytes) */
++#define	SAFE_PE_LEN_BYPASS_S	24
++
++#define	SAFE_PE_LEN_IS_DONE(_len) \
++    (((_len) & (SAFE_PE_LEN_READY | SAFE_PE_LEN_DONE)) == SAFE_PE_LEN_DONE)
++
++/* NB: these apply to HU_STAT, HM_STAT, HI_CLR, and HI_MASK */
++#define	SAFE_INT_PE_CDONE	0x00000002	/* PE context done */
++#define	SAFE_INT_PE_DDONE	0x00000008	/* PE descriptor done */
++#define	SAFE_INT_PE_ERROR	0x00000010	/* PE error */
++#define	SAFE_INT_PE_ODONE	0x00000020	/* PE operation done */
++
++#define	SAFE_HI_CFG_PULSE	0x00000001	/* use pulse interrupt */
++#define	SAFE_HI_CFG_LEVEL	0x00000000	/* use level interrupt */
++#define	SAFE_HI_CFG_AUTOCLR	0x00000002	/* auto-clear pulse interrupt */
++
++#define	SAFE_ENDIAN_PASS	0x000000e4	/* straight pass-thru */
++#define	SAFE_ENDIAN_SWAB	0x0000001b	/* swap bytes in 32-bit word */
++
++#define	SAFE_PE_DMACFG_PERESET	0x00000001	/* reset packet engine */
++#define	SAFE_PE_DMACFG_PDRRESET	0x00000002	/* reset PDR counters/ptrs */
++#define	SAFE_PE_DMACFG_SGRESET	0x00000004	/* reset scatter/gather cache */
++#define	SAFE_PE_DMACFG_FSENA	0x00000008	/* enable failsafe reset */
++#define	SAFE_PE_DMACFG_PEMODE	0x00000100	/* packet engine mode */
++#define	SAFE_PE_DMACFG_SAPREC	0x00000200	/* SA precedes packet */
++#define	SAFE_PE_DMACFG_PKFOLL	0x00000400	/* packet follows descriptor */
++#define	SAFE_PE_DMACFG_GPRBID	0x00003000	/* gather particle ring busid */
++#define	SAFE_PE_DMACFG_GPRPCI	0x00001000	/* PCI gather particle ring */
++#define	SAFE_PE_DMACFG_SPRBID	0x0000c000	/* scatter part. ring busid */
++#define	SAFE_PE_DMACFG_SPRPCI	0x00004000	/* PCI scatter part. ring */
++#define	SAFE_PE_DMACFG_ESDESC	0x00010000	/* endian swap descriptors */
++#define	SAFE_PE_DMACFG_ESSA	0x00020000	/* endian swap SA data */
++#define	SAFE_PE_DMACFG_ESPACKET	0x00040000	/* endian swap packet data */
++#define	SAFE_PE_DMACFG_ESPDESC	0x00080000	/* endian swap particle desc. */
++#define	SAFE_PE_DMACFG_NOPDRUP	0x00100000	/* supp. PDR ownership update */
++#define	SAFE_PD_EDMACFG_PCIMODE	0x01000000	/* PCI target mode */
++
++#define	SAFE_PE_DMASTAT_PEIDONE	0x00000001	/* PE core input done */
++#define	SAFE_PE_DMASTAT_PEODONE	0x00000002	/* PE core output done */
++#define	SAFE_PE_DMASTAT_ENCDONE	0x00000004	/* encryption done */
++#define	SAFE_PE_DMASTAT_IHDONE	0x00000008	/* inner hash done */
++#define	SAFE_PE_DMASTAT_OHDONE	0x00000010	/* outer hash (HMAC) done */
++#define	SAFE_PE_DMASTAT_PADFLT	0x00000020	/* crypto pad fault */
++#define	SAFE_PE_DMASTAT_ICVFLT	0x00000040	/* ICV fault */
++#define	SAFE_PE_DMASTAT_SPIMIS	0x00000080	/* SPI mismatch */
++#define	SAFE_PE_DMASTAT_CRYPTO	0x00000100	/* crypto engine timeout */
++#define	SAFE_PE_DMASTAT_CQACT	0x00000200	/* command queue active */
++#define	SAFE_PE_DMASTAT_IRACT	0x00000400	/* input request active */
++#define	SAFE_PE_DMASTAT_ORACT	0x00000800	/* output request active */
++#define	SAFE_PE_DMASTAT_PEISIZE	0x003ff000	/* PE input size:32-bit words */
++#define	SAFE_PE_DMASTAT_PEOSIZE	0xffc00000	/* PE out. size:32-bit words */
++
++#define	SAFE_PE_RINGCFG_SIZE	0x000003ff	/* ring size (descriptors) */
++#define	SAFE_PE_RINGCFG_OFFSET	0xffff0000	/* offset btw desc's (dwords) */
++#define	SAFE_PE_RINGCFG_OFFSET_S	16
++
++#define	SAFE_PE_RINGPOLL_POLL	0x00000fff	/* polling frequency/divisor */
++#define	SAFE_PE_RINGPOLL_RETRY	0x03ff0000	/* polling frequency/divisor */
++#define	SAFE_PE_RINGPOLL_CONT	0x80000000	/* continuously poll */
++
++#define	SAFE_PE_IRNGSTAT_CQAVAIL 0x00000001	/* command queue available */
++
++#define	SAFE_PE_ERNGSTAT_NEXT	0x03ff0000	/* index of next packet desc. */
++#define	SAFE_PE_ERNGSTAT_NEXT_S	16
++
++#define	SAFE_PE_IOTHRESH_INPUT	0x000003ff	/* input threshold (dwords) */
++#define	SAFE_PE_IOTHRESH_OUTPUT	0x03ff0000	/* output threshold (dwords) */
++
++#define	SAFE_PE_PARTCFG_SIZE	0x0000ffff	/* scatter particle size */
++#define	SAFE_PE_PARTCFG_GBURST	0x00030000	/* gather particle burst */
++#define	SAFE_PE_PARTCFG_GBURST_2	0x00000000
++#define	SAFE_PE_PARTCFG_GBURST_4	0x00010000
++#define	SAFE_PE_PARTCFG_GBURST_8	0x00020000
++#define	SAFE_PE_PARTCFG_GBURST_16	0x00030000
++#define	SAFE_PE_PARTCFG_SBURST	0x000c0000	/* scatter particle burst */
++#define	SAFE_PE_PARTCFG_SBURST_2	0x00000000
++#define	SAFE_PE_PARTCFG_SBURST_4	0x00040000
++#define	SAFE_PE_PARTCFG_SBURST_8	0x00080000
++#define	SAFE_PE_PARTCFG_SBURST_16	0x000c0000
++
++#define	SAFE_PE_PARTSIZE_SCAT	0xffff0000	/* scatter particle ring size */
++#define	SAFE_PE_PARTSIZE_GATH	0x0000ffff	/* gather particle ring size */
++
++#define	SAFE_CRYPTO_CTRL_3DES	0x00000001	/* enable 3DES support */
++#define	SAFE_CRYPTO_CTRL_PKEY	0x00010000	/* enable public key support */
++#define	SAFE_CRYPTO_CTRL_RNG	0x00020000	/* enable RNG support */
++
++#define	SAFE_DEVINFO_REV_MIN	0x0000000f	/* minor rev for chip */
++#define	SAFE_DEVINFO_REV_MAJ	0x000000f0	/* major rev for chip */
++#define	SAFE_DEVINFO_REV_MAJ_S	4
++#define	SAFE_DEVINFO_DES	0x00000100	/* DES/3DES support present */
++#define	SAFE_DEVINFO_ARC4	0x00000200	/* ARC4 support present */
++#define	SAFE_DEVINFO_AES	0x00000400	/* AES support present */
++#define	SAFE_DEVINFO_MD5	0x00001000	/* MD5 support present */
++#define	SAFE_DEVINFO_SHA1	0x00002000	/* SHA-1 support present */
++#define	SAFE_DEVINFO_RIPEMD	0x00004000	/* RIPEMD support present */
++#define	SAFE_DEVINFO_DEFLATE	0x00010000	/* Deflate support present */
++#define	SAFE_DEVINFO_SARAM	0x00100000	/* on-chip SA RAM present */
++#define	SAFE_DEVINFO_EMIBUS	0x00200000	/* EMI bus present */
++#define	SAFE_DEVINFO_PKEY	0x00400000	/* public key support present */
++#define	SAFE_DEVINFO_RNG	0x00800000	/* RNG present */
++
++#define	SAFE_REV(_maj, _min)	(((_maj) << SAFE_DEVINFO_REV_MAJ_S) | (_min))
++#define	SAFE_REV_MAJ(_chiprev) \
++	(((_chiprev) & SAFE_DEVINFO_REV_MAJ) >> SAFE_DEVINFO_REV_MAJ_S)
++#define	SAFE_REV_MIN(_chiprev)	((_chiprev) & SAFE_DEVINFO_REV_MIN)
++
++#define	SAFE_PK_FUNC_MULT	0x00000001	/* Multiply function */
++#define	SAFE_PK_FUNC_SQUARE	0x00000004	/* Square function */
++#define	SAFE_PK_FUNC_ADD	0x00000010	/* Add function */
++#define	SAFE_PK_FUNC_SUB	0x00000020	/* Subtract function */
++#define	SAFE_PK_FUNC_LSHIFT	0x00000040	/* Left-shift function */
++#define	SAFE_PK_FUNC_RSHIFT	0x00000080	/* Right-shift function */
++#define	SAFE_PK_FUNC_DIV	0x00000100	/* Divide function */
++#define	SAFE_PK_FUNC_CMP	0x00000400	/* Compare function */
++#define	SAFE_PK_FUNC_COPY	0x00000800	/* Copy function */
++#define	SAFE_PK_FUNC_EXP16	0x00002000	/* Exponentiate (4-bit ACT) */
++#define	SAFE_PK_FUNC_EXP4	0x00004000	/* Exponentiate (2-bit ACT) */
++#define	SAFE_PK_FUNC_RUN	0x00008000	/* start/status */
++
++#define	SAFE_RNG_STAT_BUSY	0x00000001	/* busy, data not valid */
++
++#define	SAFE_RNG_CTRL_PRE_LFSR	0x00000001	/* enable output pre-LFSR */
++#define	SAFE_RNG_CTRL_TST_MODE	0x00000002	/* enable test mode */
++#define	SAFE_RNG_CTRL_TST_RUN	0x00000004	/* start test state machine */
++#define	SAFE_RNG_CTRL_ENA_RING1	0x00000008	/* test entropy oscillator #1 */
++#define	SAFE_RNG_CTRL_ENA_RING2	0x00000010	/* test entropy oscillator #2 */
++#define	SAFE_RNG_CTRL_DIS_ALARM	0x00000020	/* disable RNG alarm reports */
++#define	SAFE_RNG_CTRL_TST_CLOCK	0x00000040	/* enable test clock */
++#define	SAFE_RNG_CTRL_SHORTEN	0x00000080	/* shorten state timers */
++#define	SAFE_RNG_CTRL_TST_ALARM	0x00000100	/* simulate alarm state */
++#define	SAFE_RNG_CTRL_RST_LFSR	0x00000200	/* reset LFSR */
++
++/*
++ * Packet engine descriptor.  Note that d_csr is a copy of the
++ * SAFE_PE_CSR register and all definitions apply, and d_len
++ * is a copy of the SAFE_PE_LEN register and all definitions apply.
++ * d_src and d_len may point directly to contiguous data or to a
++ * list of ``particle descriptors'' when using scatter/gather i/o.
++ */
++struct safe_desc {
++	u_int32_t	d_csr;			/* per-packet control/status */
++	u_int32_t	d_src;			/* source address */
++	u_int32_t	d_dst;			/* destination address */
++	u_int32_t	d_sa;			/* SA address */
++	u_int32_t	d_len;			/* length, bypass, status */
++};
++
++/*
++ * Scatter/Gather particle descriptor.
++ *
++ * NB: scatter descriptors do not specify a size; this is fixed
++ *     by the setting of the SAFE_PE_PARTCFG register.
++ */
++struct safe_pdesc {
++	u_int32_t	pd_addr;		/* particle address */
++#ifdef __BIG_ENDIAN
++	u_int16_t	pd_flags;		/* control word */
++	u_int16_t	pd_size;		/* particle size (bytes) */
++#else
++	u_int16_t	pd_flags;		/* control word */
++	u_int16_t	pd_size;		/* particle size (bytes) */
++#endif
++};
++
++#define	SAFE_PD_READY	0x0001			/* ready for processing */
++#define	SAFE_PD_DONE	0x0002			/* h/w completed processing */
++
++/*
++ * Security Association (SA) Record (Rev 1).  One of these is
++ * required for each operation processed by the packet engine.
++ */
++struct safe_sarec {
++	u_int32_t	sa_cmd0;
++	u_int32_t	sa_cmd1;
++	u_int32_t	sa_resv0;
++	u_int32_t	sa_resv1;
++	u_int32_t	sa_key[8];		/* DES/3DES/AES key */
++	u_int32_t	sa_indigest[5];		/* inner digest */
++	u_int32_t	sa_outdigest[5];	/* outer digest */
++	u_int32_t	sa_spi;			/* SPI */
++	u_int32_t	sa_seqnum;		/* sequence number */
++	u_int32_t	sa_seqmask[2];		/* sequence number mask */
++	u_int32_t	sa_resv2;
++	u_int32_t	sa_staterec;		/* address of state record */
++	u_int32_t	sa_resv3[2];
++	u_int32_t	sa_samgmt0;		/* SA management field 0 */
++	u_int32_t	sa_samgmt1;		/* SA management field 0 */
++};
++
++#define	SAFE_SA_CMD0_OP		0x00000007	/* operation code */
++#define	SAFE_SA_CMD0_OP_CRYPT	0x00000000	/* encrypt/decrypt (basic) */
++#define	SAFE_SA_CMD0_OP_BOTH	0x00000001	/* encrypt-hash/hash-decrypto */
++#define	SAFE_SA_CMD0_OP_HASH	0x00000003	/* hash (outbound-only) */
++#define	SAFE_SA_CMD0_OP_ESP	0x00000000	/* ESP in/out (proto) */
++#define	SAFE_SA_CMD0_OP_AH	0x00000001	/* AH in/out (proto) */
++#define	SAFE_SA_CMD0_INBOUND	0x00000008	/* inbound operation */
++#define	SAFE_SA_CMD0_OUTBOUND	0x00000000	/* outbound operation */
++#define	SAFE_SA_CMD0_GROUP	0x00000030	/* operation group */
++#define	SAFE_SA_CMD0_BASIC	0x00000000	/* basic operation */
++#define	SAFE_SA_CMD0_PROTO	0x00000010	/* protocol/packet operation */
++#define	SAFE_SA_CMD0_BUNDLE	0x00000020	/* bundled operation (resvd) */
++#define	SAFE_SA_CMD0_PAD	0x000000c0	/* crypto pad method */
++#define	SAFE_SA_CMD0_PAD_IPSEC	0x00000000	/* IPsec padding */
++#define	SAFE_SA_CMD0_PAD_PKCS7	0x00000040	/* PKCS#7 padding */
++#define	SAFE_SA_CMD0_PAD_CONS	0x00000080	/* constant padding */
++#define	SAFE_SA_CMD0_PAD_ZERO	0x000000c0	/* zero padding */
++#define	SAFE_SA_CMD0_CRYPT_ALG	0x00000f00	/* symmetric crypto algorithm */
++#define	SAFE_SA_CMD0_DES	0x00000000	/* DES crypto algorithm */
++#define	SAFE_SA_CMD0_3DES	0x00000100	/* 3DES crypto algorithm */
++#define	SAFE_SA_CMD0_AES	0x00000300	/* AES crypto algorithm */
++#define	SAFE_SA_CMD0_CRYPT_NULL	0x00000f00	/* null crypto algorithm */
++#define	SAFE_SA_CMD0_HASH_ALG	0x0000f000	/* hash algorithm */
++#define	SAFE_SA_CMD0_MD5	0x00000000	/* MD5 hash algorithm */
++#define	SAFE_SA_CMD0_SHA1	0x00001000	/* SHA-1 hash algorithm */
++#define	SAFE_SA_CMD0_HASH_NULL	0x0000f000	/* null hash algorithm */
++#define	SAFE_SA_CMD0_HDR_PROC	0x00080000	/* header processing */
++#define	SAFE_SA_CMD0_IBUSID	0x00300000	/* input bus id */
++#define	SAFE_SA_CMD0_IPCI	0x00100000	/* PCI input bus id */
++#define	SAFE_SA_CMD0_OBUSID	0x00c00000	/* output bus id */
++#define	SAFE_SA_CMD0_OPCI	0x00400000	/* PCI output bus id */
++#define	SAFE_SA_CMD0_IVLD	0x03000000	/* IV loading */
++#define	SAFE_SA_CMD0_IVLD_NONE	0x00000000	/* IV no load (reuse) */
++#define	SAFE_SA_CMD0_IVLD_IBUF	0x01000000	/* IV load from input buffer */
++#define	SAFE_SA_CMD0_IVLD_STATE	0x02000000	/* IV load from state */
++#define	SAFE_SA_CMD0_HSLD	0x0c000000	/* hash state loading */
++#define	SAFE_SA_CMD0_HSLD_SA	0x00000000	/* hash state load from SA */
++#define	SAFE_SA_CMD0_HSLD_STATE	0x08000000	/* hash state load from state */
++#define	SAFE_SA_CMD0_HSLD_NONE	0x0c000000	/* hash state no load */
++#define	SAFE_SA_CMD0_SAVEIV	0x10000000	/* save IV */
++#define	SAFE_SA_CMD0_SAVEHASH	0x20000000	/* save hash state */
++#define	SAFE_SA_CMD0_IGATHER	0x40000000	/* input gather */
++#define	SAFE_SA_CMD0_OSCATTER	0x80000000	/* output scatter */
++
++#define	SAFE_SA_CMD1_HDRCOPY	0x00000002	/* copy header to output */
++#define	SAFE_SA_CMD1_PAYCOPY	0x00000004	/* copy payload to output */
++#define	SAFE_SA_CMD1_PADCOPY	0x00000008	/* copy pad to output */
++#define	SAFE_SA_CMD1_IPV4	0x00000000	/* IPv4 protocol */
++#define	SAFE_SA_CMD1_IPV6	0x00000010	/* IPv6 protocol */
++#define	SAFE_SA_CMD1_MUTABLE	0x00000020	/* mutable bit processing */
++#define	SAFE_SA_CMD1_SRBUSID	0x000000c0	/* state record bus id */
++#define	SAFE_SA_CMD1_SRPCI	0x00000040	/* state record from PCI */
++#define	SAFE_SA_CMD1_CRMODE	0x00000300	/* crypto mode */
++#define	SAFE_SA_CMD1_ECB	0x00000000	/* ECB crypto mode */
++#define	SAFE_SA_CMD1_CBC	0x00000100	/* CBC crypto mode */
++#define	SAFE_SA_CMD1_OFB	0x00000200	/* OFB crypto mode */
++#define	SAFE_SA_CMD1_CFB	0x00000300	/* CFB crypto mode */
++#define	SAFE_SA_CMD1_CRFEEDBACK	0x00000c00	/* crypto feedback mode */
++#define	SAFE_SA_CMD1_64BIT	0x00000000	/* 64-bit crypto feedback */
++#define	SAFE_SA_CMD1_8BIT	0x00000400	/* 8-bit crypto feedback */
++#define	SAFE_SA_CMD1_1BIT	0x00000800	/* 1-bit crypto feedback */
++#define	SAFE_SA_CMD1_128BIT	0x00000c00	/* 128-bit crypto feedback */
++#define	SAFE_SA_CMD1_OPTIONS	0x00001000	/* HMAC/options mutable bit */
++#define	SAFE_SA_CMD1_HMAC	SAFE_SA_CMD1_OPTIONS
++#define	SAFE_SA_CMD1_SAREV1	0x00008000	/* SA Revision 1 */
++#define	SAFE_SA_CMD1_OFFSET	0x00ff0000	/* hash/crypto offset(dwords) */
++#define	SAFE_SA_CMD1_OFFSET_S	16
++#define	SAFE_SA_CMD1_AESKEYLEN	0x0f000000	/* AES key length */
++#define	SAFE_SA_CMD1_AES128	0x02000000	/* 128-bit AES key */
++#define	SAFE_SA_CMD1_AES192	0x03000000	/* 192-bit AES key */
++#define	SAFE_SA_CMD1_AES256	0x04000000	/* 256-bit AES key */
++
++/* 
++ * Security Associate State Record (Rev 1).
++ */
++struct safe_sastate {
++	u_int32_t	sa_saved_iv[4];		/* saved IV (DES/3DES/AES) */
++	u_int32_t	sa_saved_hashbc;	/* saved hash byte count */
++	u_int32_t	sa_saved_indigest[5];	/* saved inner digest */
++};
++#endif /* _SAFE_SAFEREG_H_ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/safevar.h linux-2.6.23.16/crypto/ocf/safe/safevar.h
+--- linux-2.6.23.16.old/crypto/ocf/safe/safevar.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/safevar.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,230 @@
++/*-
++ * The linux port of this code done by David McCullough
++ * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com>
++ * The license and original author are listed below.
++ *
++ * Copyright (c) 2003 Sam Leffler, Errno Consulting
++ * Copyright (c) 2003 Global Technology Associates, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * $FreeBSD: src/sys/dev/safe/safevar.h,v 1.2 2006/05/17 18:34:26 pjd Exp $
++ */
++#ifndef _SAFE_SAFEVAR_H_
++#define	_SAFE_SAFEVAR_H_
++
++/* Maximum queue length */
++#ifndef SAFE_MAX_NQUEUE
++#define SAFE_MAX_NQUEUE	60
++#endif
++
++#define	SAFE_MAX_PART		64	/* Maximum scatter/gather depth */
++#define	SAFE_DMA_BOUNDARY	0	/* No boundary for source DMA ops */
++#define	SAFE_MAX_DSIZE		2048 /* MCLBYTES Fixed scatter particle size */
++#define	SAFE_MAX_SSIZE		0x0ffff	/* Maximum gather particle size */
++#define	SAFE_MAX_DMA		0xfffff	/* Maximum PE operand size (20 bits) */
++/* total src+dst particle descriptors */
++#define	SAFE_TOTAL_DPART	(SAFE_MAX_NQUEUE * SAFE_MAX_PART)
++#define	SAFE_TOTAL_SPART	(SAFE_MAX_NQUEUE * SAFE_MAX_PART)
++
++#define	SAFE_RNG_MAXBUFSIZ	128	/* 32-bit words */
++
++#define	SAFE_CARD(sid)		(((sid) & 0xf0000000) >> 28)
++#define	SAFE_SESSION(sid)	( (sid) & 0x0fffffff)
++#define	SAFE_SID(crd, sesn)	(((crd) << 28) | ((sesn) & 0x0fffffff))
++
++#define SAFE_DEF_RTY		0xff	/* PCI Retry Timeout */
++#define SAFE_DEF_TOUT		0xff	/* PCI TRDY Timeout */
++#define SAFE_DEF_CACHELINE	0x01	/* Cache Line setting */
++
++#ifdef __KERNEL__
++/*
++ * State associated with the allocation of each chunk
++ * of memory setup for DMA.
++ */
++struct safe_dma_alloc {
++	dma_addr_t		dma_paddr;
++	void			*dma_vaddr;
++};
++
++/*
++ * Cryptographic operand state.  One of these exists for each
++ * source and destination operand passed in from the crypto
++ * subsystem.  When possible source and destination operands
++ * refer to the same memory.  More often they are distinct.
++ * We track the virtual address of each operand as well as
++ * where each is mapped for DMA.
++ */
++struct safe_operand {
++	union {
++		struct sk_buff *skb;
++		struct uio *io;
++	} u;
++	void			*map;
++	int				mapsize;	/* total number of bytes in segs */
++	struct {
++		dma_addr_t	ds_addr;
++		int			ds_len;
++		int			ds_tlen;
++	} segs[SAFE_MAX_PART];
++	int				nsegs;
++};
++
++/*
++ * Packet engine ring entry and cryptographic operation state.
++ * The packet engine requires a ring of descriptors that contain
++ * pointers to various cryptographic state.  However the ring
++ * configuration register allows you to specify an arbitrary size
++ * for ring entries.  We use this feature to collect most of the
++ * state for each cryptographic request into one spot.  Other than
++ * ring entries only the ``particle descriptors'' (scatter/gather
++ * lists) and the actual operand data are kept separate.  The
++ * particle descriptors must also be organized in rings.  The
++ * operand data can be located aribtrarily (modulo alignment constraints).
++ *
++ * Note that the descriptor ring is mapped onto the PCI bus so
++ * the hardware can DMA data.  This means the entire ring must be
++ * contiguous.
++ */
++struct safe_ringentry {
++	struct safe_desc	re_desc;	/* command descriptor */
++	struct safe_sarec	re_sa;		/* SA record */
++	struct safe_sastate	re_sastate;	/* SA state record */
++
++	struct cryptop		*re_crp;	/* crypto operation */
++
++	struct safe_operand	re_src;		/* source operand */
++	struct safe_operand	re_dst;		/* destination operand */
++
++	int			re_sesn;	/* crypto session ID */
++	int			re_flags;
++#define	SAFE_QFLAGS_COPYOUTIV	0x1		/* copy back on completion */
++#define	SAFE_QFLAGS_COPYOUTICV	0x2		/* copy back on completion */
++};
++
++#define	re_src_skb	re_src.u.skb
++#define	re_src_io	re_src.u.io
++#define	re_src_map	re_src.map
++#define	re_src_nsegs	re_src.nsegs
++#define	re_src_segs	re_src.segs
++#define	re_src_mapsize	re_src.mapsize
++
++#define	re_dst_skb	re_dst.u.skb
++#define	re_dst_io	re_dst.u.io
++#define	re_dst_map	re_dst.map
++#define	re_dst_nsegs	re_dst.nsegs
++#define	re_dst_segs	re_dst.segs
++#define	re_dst_mapsize	re_dst.mapsize
++
++struct rndstate_test;
++
++struct safe_session {
++	u_int32_t	ses_used;
++	u_int32_t	ses_klen;		/* key length in bits */
++	u_int32_t	ses_key[8];		/* DES/3DES/AES key */
++	u_int32_t	ses_mlen;		/* hmac length in bytes */
++	u_int32_t	ses_hminner[5];		/* hmac inner state */
++	u_int32_t	ses_hmouter[5];		/* hmac outer state */
++	u_int32_t	ses_iv[4];		/* DES/3DES/AES iv */
++};
++
++struct safe_pkq {
++	struct list_head	pkq_list;
++	struct cryptkop		*pkq_krp;
++};
++
++struct safe_softc {
++	softc_device_decl	sc_dev;
++	u32			sc_irq;
++
++	struct pci_dev		*sc_pcidev;
++	ocf_iomem_t		sc_base_addr;
++
++	u_int			sc_chiprev;	/* major/minor chip revision */
++	int			sc_flags;	/* device specific flags */
++#define	SAFE_FLAGS_KEY		0x01		/* has key accelerator */
++#define	SAFE_FLAGS_RNG		0x02		/* hardware rng */
++	int			sc_suspended;
++	int			sc_needwakeup;	/* notify crypto layer */
++	int32_t			sc_cid;		/* crypto tag */
++
++	struct safe_dma_alloc	sc_ringalloc;	/* PE ring allocation state */
++	struct safe_ringentry	*sc_ring;	/* PE ring */
++	struct safe_ringentry	*sc_ringtop;	/* PE ring top */
++	struct safe_ringentry	*sc_front;	/* next free entry */
++	struct safe_ringentry	*sc_back;	/* next pending entry */
++	int			sc_nqchip;	/* # passed to chip */
++	spinlock_t		sc_ringmtx;	/* PE ring lock */
++	struct safe_pdesc	*sc_spring;	/* src particle ring */
++	struct safe_pdesc	*sc_springtop;	/* src particle ring top */
++	struct safe_pdesc	*sc_spfree;	/* next free src particle */
++	struct safe_dma_alloc	sc_spalloc;	/* src particle ring state */
++	struct safe_pdesc	*sc_dpring;	/* dest particle ring */
++	struct safe_pdesc	*sc_dpringtop;	/* dest particle ring top */
++	struct safe_pdesc	*sc_dpfree;	/* next free dest particle */
++	struct safe_dma_alloc	sc_dpalloc;	/* dst particle ring state */
++	int			sc_nsessions;	/* # of sessions */
++	struct safe_session	*sc_sessions;	/* sessions */
++
++	struct timer_list	sc_pkto;	/* PK polling */
++	spinlock_t		sc_pkmtx;	/* PK lock */
++	struct list_head	sc_pkq;		/* queue of PK requests */
++	struct safe_pkq		*sc_pkq_cur;	/* current processing request */
++	u_int32_t		sc_pk_reslen, sc_pk_resoff;
++
++	int			sc_max_dsize;	/* maximum safe DMA size */
++};
++#endif /* __KERNEL__ */
++
++struct safe_stats {
++	u_int64_t st_ibytes;
++	u_int64_t st_obytes;
++	u_int32_t st_ipackets;
++	u_int32_t st_opackets;
++	u_int32_t st_invalid;		/* invalid argument */
++	u_int32_t st_badsession;	/* invalid session id */
++	u_int32_t st_badflags;		/* flags indicate !(mbuf | uio) */
++	u_int32_t st_nodesc;		/* op submitted w/o descriptors */
++	u_int32_t st_badalg;		/* unsupported algorithm */
++	u_int32_t st_ringfull;		/* PE descriptor ring full */
++	u_int32_t st_peoperr;		/* PE marked error */
++	u_int32_t st_dmaerr;		/* PE DMA error */
++	u_int32_t st_bypasstoobig;	/* bypass > 96 bytes */
++	u_int32_t st_skipmismatch;	/* enc part begins before auth part */
++	u_int32_t st_lenmismatch;	/* enc length different auth length */
++	u_int32_t st_coffmisaligned;	/* crypto offset not 32-bit aligned */
++	u_int32_t st_cofftoobig;	/* crypto offset > 255 words */
++	u_int32_t st_iovmisaligned;	/* iov op not aligned */
++	u_int32_t st_iovnotuniform;	/* iov op not suitable */
++	u_int32_t st_unaligned;		/* unaligned src caused copy */
++	u_int32_t st_notuniform;	/* non-uniform src caused copy */
++	u_int32_t st_nomap;		/* bus_dmamap_create failed */
++	u_int32_t st_noload;		/* bus_dmamap_load_* failed */
++	u_int32_t st_nombuf;		/* MGET* failed */
++	u_int32_t st_nomcl;		/* MCLGET* failed */
++	u_int32_t st_maxqchip;		/* max mcr1 ops out for processing */
++	u_int32_t st_rng;		/* RNG requests */
++	u_int32_t st_rngalarm;		/* RNG alarm requests */
++	u_int32_t st_noicvcopy;		/* ICV data copies suppressed */
++};
++#endif /* _SAFE_SAFEVAR_H_ */
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/sha1.c linux-2.6.23.16/crypto/ocf/safe/sha1.c
+--- linux-2.6.23.16.old/crypto/ocf/safe/sha1.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/sha1.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,279 @@
++/*	$KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp $	*/
++/*
++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++/*
++ * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
++ * based on: http://csrc.nist.gov/fips/fip180-1.txt
++ * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
++ */
++
++#if 0
++#include <sys/cdefs.h>
++__FBSDID("$FreeBSD: src/sys/crypto/sha1.c,v 1.9 2003/06/10 21:36:57 obrien Exp $");
++
++#include <sys/types.h>
++#include <sys/cdefs.h>
++#include <sys/time.h>
++#include <sys/systm.h>
++
++#include <crypto/sha1.h>
++#endif
++
++/* sanity check */
++#if BYTE_ORDER != BIG_ENDIAN
++# if BYTE_ORDER != LITTLE_ENDIAN
++#  define unsupported 1
++# endif
++#endif
++
++#ifndef unsupported
++
++/* constant table */
++static u_int32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
++#define	K(t)	_K[(t) / 20]
++
++#define	F0(b, c, d)	(((b) & (c)) | ((~(b)) & (d)))
++#define	F1(b, c, d)	(((b) ^ (c)) ^ (d))
++#define	F2(b, c, d)	(((b) & (c)) | ((b) & (d)) | ((c) & (d)))
++#define	F3(b, c, d)	(((b) ^ (c)) ^ (d))
++
++#define	S(n, x)		(((x) << (n)) | ((x) >> (32 - n)))
++
++#undef H
++#define	H(n)	(ctxt->h.b32[(n)])
++#define	COUNT	(ctxt->count)
++#define	BCOUNT	(ctxt->c.b64[0] / 8)
++#define	W(n)	(ctxt->m.b32[(n)])
++
++#define	PUTBYTE(x)	{ \
++	ctxt->m.b8[(COUNT % 64)] = (x);		\
++	COUNT++;				\
++	COUNT %= 64;				\
++	ctxt->c.b64[0] += 8;			\
++	if (COUNT % 64 == 0)			\
++		sha1_step(ctxt);		\
++     }
++
++#define	PUTPAD(x)	{ \
++	ctxt->m.b8[(COUNT % 64)] = (x);		\
++	COUNT++;				\
++	COUNT %= 64;				\
++	if (COUNT % 64 == 0)			\
++		sha1_step(ctxt);		\
++     }
++
++static void sha1_step(struct sha1_ctxt *);
++
++static void
++sha1_step(ctxt)
++	struct sha1_ctxt *ctxt;
++{
++	u_int32_t	a, b, c, d, e;
++	size_t t, s;
++	u_int32_t	tmp;
++
++#if BYTE_ORDER == LITTLE_ENDIAN
++	struct sha1_ctxt tctxt;
++	bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);
++	ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
++	ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
++	ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
++	ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
++	ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
++	ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
++	ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
++	ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
++	ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
++	ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
++	ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
++	ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
++	ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
++	ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
++	ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
++	ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
++	ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
++	ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
++	ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
++	ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
++	ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
++	ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
++	ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
++	ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
++	ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
++	ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
++	ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
++	ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
++	ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
++	ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
++	ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
++	ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
++#endif
++
++	a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
++
++	for (t = 0; t < 20; t++) {
++		s = t & 0x0f;
++		if (t >= 16) {
++			W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
++		}
++		tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
++		e = d; d = c; c = S(30, b); b = a; a = tmp;
++	}
++	for (t = 20; t < 40; t++) {
++		s = t & 0x0f;
++		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
++		tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
++		e = d; d = c; c = S(30, b); b = a; a = tmp;
++	}
++	for (t = 40; t < 60; t++) {
++		s = t & 0x0f;
++		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
++		tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
++		e = d; d = c; c = S(30, b); b = a; a = tmp;
++	}
++	for (t = 60; t < 80; t++) {
++		s = t & 0x0f;
++		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
++		tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
++		e = d; d = c; c = S(30, b); b = a; a = tmp;
++	}
++
++	H(0) = H(0) + a;
++	H(1) = H(1) + b;
++	H(2) = H(2) + c;
++	H(3) = H(3) + d;
++	H(4) = H(4) + e;
++
++	bzero(&ctxt->m.b8[0], 64);
++}
++
++/*------------------------------------------------------------*/
++
++void
++sha1_init(ctxt)
++	struct sha1_ctxt *ctxt;
++{
++	bzero(ctxt, sizeof(struct sha1_ctxt));
++	H(0) = 0x67452301;
++	H(1) = 0xefcdab89;
++	H(2) = 0x98badcfe;
++	H(3) = 0x10325476;
++	H(4) = 0xc3d2e1f0;
++}
++
++void
++sha1_pad(ctxt)
++	struct sha1_ctxt *ctxt;
++{
++	size_t padlen;		/*pad length in bytes*/
++	size_t padstart;
++
++	PUTPAD(0x80);
++
++	padstart = COUNT % 64;
++	padlen = 64 - padstart;
++	if (padlen < 8) {
++		bzero(&ctxt->m.b8[padstart], padlen);
++		COUNT += padlen;
++		COUNT %= 64;
++		sha1_step(ctxt);
++		padstart = COUNT % 64;	/* should be 0 */
++		padlen = 64 - padstart;	/* should be 64 */
++	}
++	bzero(&ctxt->m.b8[padstart], padlen - 8);
++	COUNT += (padlen - 8);
++	COUNT %= 64;
++#if BYTE_ORDER == BIG_ENDIAN
++	PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
++	PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
++	PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
++	PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
++#else
++	PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
++	PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
++	PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
++	PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
++#endif
++}
++
++void
++sha1_loop(ctxt, input, len)
++	struct sha1_ctxt *ctxt;
++	const u_int8_t *input;
++	size_t len;
++{
++	size_t gaplen;
++	size_t gapstart;
++	size_t off;
++	size_t copysiz;
++
++	off = 0;
++
++	while (off < len) {
++		gapstart = COUNT % 64;
++		gaplen = 64 - gapstart;
++
++		copysiz = (gaplen < len - off) ? gaplen : len - off;
++		bcopy(&input[off], &ctxt->m.b8[gapstart], copysiz);
++		COUNT += copysiz;
++		COUNT %= 64;
++		ctxt->c.b64[0] += copysiz * 8;
++		if (COUNT % 64 == 0)
++			sha1_step(ctxt);
++		off += copysiz;
++	}
++}
++
++void
++sha1_result(ctxt, digest0)
++	struct sha1_ctxt *ctxt;
++	caddr_t digest0;
++{
++	u_int8_t *digest;
++
++	digest = (u_int8_t *)digest0;
++	sha1_pad(ctxt);
++#if BYTE_ORDER == BIG_ENDIAN
++	bcopy(&ctxt->h.b8[0], digest, 20);
++#else
++	digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
++	digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
++	digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
++	digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
++	digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
++	digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
++	digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
++	digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
++	digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
++	digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
++#endif
++}
++
++#endif /*unsupported*/
+diff -urN linux-2.6.23.16.old/crypto/ocf/safe/sha1.h linux-2.6.23.16/crypto/ocf/safe/sha1.h
+--- linux-2.6.23.16.old/crypto/ocf/safe/sha1.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/safe/sha1.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,72 @@
++/*	$FreeBSD: src/sys/crypto/sha1.h,v 1.8 2002/03/20 05:13:50 alfred Exp $	*/
++/*	$KAME: sha1.h,v 1.5 2000/03/27 04:36:23 sumikawa Exp $	*/
++
++/*
++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++/*
++ * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
++ * based on: http://csrc.nist.gov/fips/fip180-1.txt
++ * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
++ */
++
++#ifndef _NETINET6_SHA1_H_
++#define _NETINET6_SHA1_H_
++
++struct sha1_ctxt {
++	union {
++		u_int8_t	b8[20];
++		u_int32_t	b32[5];
++	} h;
++	union {
++		u_int8_t	b8[8];
++		u_int64_t	b64[1];
++	} c;
++	union {
++		u_int8_t	b8[64];
++		u_int32_t	b32[16];
++	} m;
++	u_int8_t	count;
++};
++
++#ifdef __KERNEL__
++extern void sha1_init(struct sha1_ctxt *);
++extern void sha1_pad(struct sha1_ctxt *);
++extern void sha1_loop(struct sha1_ctxt *, const u_int8_t *, size_t);
++extern void sha1_result(struct sha1_ctxt *, caddr_t);
++
++/* compatibilty with other SHA1 source codes */
++typedef struct sha1_ctxt SHA1_CTX;
++#define SHA1Init(x)		sha1_init((x))
++#define SHA1Update(x, y, z)	sha1_loop((x), (y), (z))
++#define SHA1Final(x, y)		sha1_result((y), (x))
++#endif /* __KERNEL__ */
++
++#define	SHA1_RESULTLEN	(160/8)
++
++#endif /*_NETINET6_SHA1_H_*/
+diff -urN linux-2.6.23.16.old/crypto/ocf/talitos/Makefile linux-2.6.23.16/crypto/ocf/talitos/Makefile
+--- linux-2.6.23.16.old/crypto/ocf/talitos/Makefile	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/talitos/Makefile	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,12 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_TALITOS) += talitos.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff -urN linux-2.6.23.16.old/crypto/ocf/talitos/talitos.c linux-2.6.23.16/crypto/ocf/talitos/talitos.c
+--- linux-2.6.23.16.old/crypto/ocf/talitos/talitos.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/talitos/talitos.c	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,1341 @@
++/*
++ * crypto/ocf/talitos/talitos.c
++ *
++ * An OCF-Linux module that uses Freescale's SEC to do the crypto.
++ * Based on crypto/ocf/hifn and crypto/ocf/safe OCF drivers
++ *
++ * Copyright (c) 2006 Freescale Semiconductor, Inc.
++ *
++ * This code written by Kim A. B. Phillips <kim.phillips@freescale.com>
++ * some code copied from files with the following:
++ * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * ---------------------------------------------------------------------------
++ *
++ * NOTES:
++ *
++ * The Freescale SEC (also known as 'talitos') resides on the
++ * internal bus, and runs asynchronous to the processor core.  It has
++ * a wide gamut of cryptographic acceleration features, including single-
++ * pass IPsec (also known as algorithm chaining).  To properly utilize 
++ * all of the SEC's performance enhancing features, further reworking 
++ * of higher level code (framework, applications) will be necessary.
++ *
++ * The following table shows which SEC version is present in which devices:
++ * 
++ * Devices       SEC version
++ *
++ * 8272, 8248    SEC 1.0
++ * 885, 875      SEC 1.2
++ * 8555E, 8541E  SEC 2.0
++ * 8349E         SEC 2.01
++ * 8548E         SEC 2.1
++ *
++ * The following table shows the features offered by each SEC version:
++ *
++ * 	                       Max.   chan-
++ * version  Bus I/F       Clock  nels  DEU AESU AFEU MDEU PKEU RNG KEU
++ *
++ * SEC 1.0  internal 64b  100MHz   4     1    1    1    1    1   1   0
++ * SEC 1.2  internal 32b   66MHz   1     1    1    0    1    0   0   0
++ * SEC 2.0  internal 64b  166MHz   4     1    1    1    1    1   1   0
++ * SEC 2.01 internal 64b  166MHz   4     1    1    1    1    1   1   0
++ * SEC 2.1  internal 64b  333MHz   4     1    1    1    1    1   1   1
++ *
++ * Each execution unit in the SEC has two modes of execution; channel and
++ * slave/debug.  This driver employs the channel infrastructure in the
++ * device for convenience.  Only the RNG is directly accessed due to the
++ * convenience of its random fifo pool.  The relationship between the
++ * channels and execution units is depicted in the following diagram:
++ *
++ *    -------   ------------
++ * ---| ch0 |---|          |
++ *    -------   |          |
++ *              |          |------+-------+-------+-------+------------
++ *    -------   |          |      |       |       |       |           |
++ * ---| ch1 |---|          |      |       |       |       |           |
++ *    -------   |          |   ------  ------  ------  ------      ------
++ *              |controller|   |DEU |  |AESU|  |MDEU|  |PKEU| ...  |RNG |
++ *    -------   |          |   ------  ------  ------  ------      ------
++ * ---| ch2 |---|          |      |       |       |       |           |
++ *    -------   |          |      |       |       |       |           |
++ *              |          |------+-------+-------+-------+------------
++ *    -------   |          |
++ * ---| ch3 |---|          |
++ *    -------   ------------
++ *
++ * Channel ch0 may drive an aes operation to the aes unit (AESU),
++ * and, at the same time, ch1 may drive a message digest operation
++ * to the mdeu. Each channel has an input descriptor FIFO, and the 
++ * FIFO can contain, e.g. on the 8541E, up to 24 entries, before a
++ * a buffer overrun error is triggered. The controller is responsible
++ * for fetching the data from descriptor pointers, and passing the 
++ * data to the appropriate EUs. The controller also writes the 
++ * cryptographic operation's result to memory. The SEC notifies 
++ * completion by triggering an interrupt and/or setting the 1st byte 
++ * of the hdr field to 0xff.
++ *
++ * TODO:
++ * o support more algorithms
++ * o support more versions of the SEC
++ * o add support for linux 2.4
++ * o scatter-gather (sg) support
++ * o add support for public key ops (PKEU)
++ * o add statistics
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/random.h>
++#include <linux/skbuff.h>
++#include <asm/scatterlist.h>
++#include <linux/dma-mapping.h>  /* dma_map_single() */
++#include <linux/moduleparam.h>
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
++#include <linux/platform_device.h>
++#endif
++
++#include <cryptodev.h>
++#include <uio.h>
++
++#define DRV_NAME "talitos" 
++
++#include "talitos_dev.h"
++#include "talitos_soft.h"
++
++#define read_random(p,l) get_random_bytes(p,l)
++
++const char talitos_driver_name[] = "Talitos OCF";
++const char talitos_driver_version[] = "0.2";
++
++static int talitos_newsession(device_t dev, u_int32_t *sidp,
++								struct cryptoini *cri);
++static int talitos_freesession(device_t dev, u_int64_t tid);
++static int talitos_process(device_t dev, struct cryptop *crp, int hint);
++static void dump_talitos_status(struct talitos_softc *sc);
++static int talitos_submit(struct talitos_softc *sc, struct talitos_desc *td, 
++								int chsel);
++static void talitos_doneprocessing(struct talitos_softc *sc);
++static void talitos_init_device(struct talitos_softc *sc);
++static void talitos_reset_device_master(struct talitos_softc *sc);
++static void talitos_reset_device(struct talitos_softc *sc);
++static void talitos_errorprocessing(struct talitos_softc *sc);
++static int talitos_probe(struct platform_device *pdev);
++static int talitos_remove(struct platform_device *pdev);
++#ifdef CONFIG_OCF_RANDOMHARVEST
++static int talitos_read_random(void *arg, u_int32_t *buf, int maxwords);
++static void talitos_rng_init(struct talitos_softc *sc);
++#endif
++
++static device_method_t talitos_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	talitos_newsession),
++	DEVMETHOD(cryptodev_freesession,talitos_freesession),
++	DEVMETHOD(cryptodev_process,	talitos_process),
++};
++
++#define debug talitos_debug
++int talitos_debug = 0;
++module_param(talitos_debug, int, 0644);
++MODULE_PARM_DESC(talitos_debug, "Enable debug");
++
++static inline void talitos_write(volatile unsigned *addr, u32 val)
++{
++        out_be32(addr, val);
++}
++
++static inline u32 talitos_read(volatile unsigned *addr)
++{
++        u32 val;
++        val = in_be32(addr);
++        return val;
++}
++
++static void dump_talitos_status(struct talitos_softc *sc)
++{
++	unsigned int v, v_hi, i, *ptr;
++	v = talitos_read(sc->sc_base_addr + TALITOS_MCR);
++	v_hi = talitos_read(sc->sc_base_addr + TALITOS_MCR_HI);
++	printk(KERN_INFO "%s: MCR          0x%08x_%08x\n",
++			device_get_nameunit(sc->sc_cdev), v, v_hi);
++	v = talitos_read(sc->sc_base_addr + TALITOS_IMR);
++	v_hi = talitos_read(sc->sc_base_addr + TALITOS_IMR_HI);
++	printk(KERN_INFO "%s: IMR          0x%08x_%08x\n",
++			device_get_nameunit(sc->sc_cdev), v, v_hi);
++	v = talitos_read(sc->sc_base_addr + TALITOS_ISR);
++	v_hi = talitos_read(sc->sc_base_addr + TALITOS_ISR_HI);
++	printk(KERN_INFO "%s: ISR          0x%08x_%08x\n",
++			device_get_nameunit(sc->sc_cdev), v, v_hi);
++	for (i = 0; i < sc->sc_num_channels; i++) { 
++		v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
++			TALITOS_CH_CDPR);
++		v_hi = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
++			TALITOS_CH_CDPR_HI);
++		printk(KERN_INFO "%s: CDPR     ch%d 0x%08x_%08x\n", 
++				device_get_nameunit(sc->sc_cdev), i, v, v_hi);
++	}
++	for (i = 0; i < sc->sc_num_channels; i++) { 
++		v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
++			TALITOS_CH_CCPSR);
++		v_hi = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
++			TALITOS_CH_CCPSR_HI);
++		printk(KERN_INFO "%s: CCPSR    ch%d 0x%08x_%08x\n", 
++				device_get_nameunit(sc->sc_cdev), i, v, v_hi);
++	}
++	ptr = sc->sc_base_addr + TALITOS_CH_DESCBUF;
++	for (i = 0; i < 16; i++) { 
++		v = talitos_read(ptr++); v_hi = talitos_read(ptr++);
++		printk(KERN_INFO "%s: DESCBUF  ch0 0x%08x_%08x (tdp%02d)\n", 
++				device_get_nameunit(sc->sc_cdev), v, v_hi, i);
++	}
++	return;
++}
++
++
++#ifdef CONFIG_OCF_RANDOMHARVEST
++/* 
++ * pull random numbers off the RNG FIFO, not exceeding amount available
++ */
++static int
++talitos_read_random(void *arg, u_int32_t *buf, int maxwords)
++{
++	struct talitos_softc *sc = (struct talitos_softc *) arg;
++	int rc;
++	u_int32_t v;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	/* check for things like FIFO underflow */
++	v = talitos_read(sc->sc_base_addr + TALITOS_RNGISR_HI);
++	if (unlikely(v)) {
++		printk(KERN_ERR "%s: RNGISR_HI error %08x\n",
++				device_get_nameunit(sc->sc_cdev), v);
++		return 0;
++	}
++	/*
++	 * OFL is number of available 64-bit words, 
++	 * shift and convert to a 32-bit word count
++	 */
++	v = talitos_read(sc->sc_base_addr + TALITOS_RNGSR_HI);
++	v = (v & TALITOS_RNGSR_HI_OFL) >> (16 - 1);
++	if (maxwords > v)
++		maxwords = v;
++	for (rc = 0; rc < maxwords; rc++) {
++		buf[rc] = talitos_read(sc->sc_base_addr + 
++			TALITOS_RNG_FIFO + rc*sizeof(u_int32_t));
++	}
++	if (maxwords & 1) {
++		/* 
++		 * RNG will complain with an AE in the RNGISR
++		 * if we don't complete the pairs of 32-bit reads
++		 * to its 64-bit register based FIFO
++		 */
++		v = talitos_read(sc->sc_base_addr + 
++			TALITOS_RNG_FIFO + rc*sizeof(u_int32_t));
++	}
++
++	return rc;
++}
++
++static void
++talitos_rng_init(struct talitos_softc *sc)
++{
++	u_int32_t v;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++	/* reset RNG EU */
++	v = talitos_read(sc->sc_base_addr + TALITOS_RNGRCR_HI);
++	v |= TALITOS_RNGRCR_HI_SR;
++	talitos_write(sc->sc_base_addr + TALITOS_RNGRCR_HI, v);
++	while ((talitos_read(sc->sc_base_addr + TALITOS_RNGSR_HI) 
++		& TALITOS_RNGSR_HI_RD) == 0)
++			cpu_relax();
++	/*
++	 * we tell the RNG to start filling the RNG FIFO
++	 * by writing the RNGDSR 
++	 */
++	v = talitos_read(sc->sc_base_addr + TALITOS_RNGDSR_HI);
++	talitos_write(sc->sc_base_addr + TALITOS_RNGDSR_HI, v);
++	/*
++	 * 64 bits of data will be pushed onto the FIFO every 
++	 * 256 SEC cycles until the FIFO is full.  The RNG then 
++	 * attempts to keep the FIFO full.
++	 */
++	v = talitos_read(sc->sc_base_addr + TALITOS_RNGISR_HI);
++	if (v) {
++		printk(KERN_ERR "%s: RNGISR_HI error %08x\n",
++			device_get_nameunit(sc->sc_cdev), v);
++		return;
++	}
++	/*
++	 * n.b. we need to add a FIPS test here - if the RNG is going 
++	 * to fail, it's going to fail at reset time
++	 */
++	return;
++}
++#endif /* CONFIG_OCF_RANDOMHARVEST */
++
++/*
++ * Generate a new software session.
++ */
++static int
++talitos_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
++{
++	struct cryptoini *c, *encini = NULL, *macini = NULL;
++	struct talitos_softc *sc = device_get_softc(dev);
++	struct talitos_session *ses = NULL;
++	int sesn;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++	if (sidp == NULL || cri == NULL || sc == NULL) {
++		DPRINTF("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++	for (c = cri; c != NULL; c = c->cri_next) {
++		if (c->cri_alg == CRYPTO_MD5 ||
++		    c->cri_alg == CRYPTO_MD5_HMAC ||
++		    c->cri_alg == CRYPTO_SHA1 ||
++		    c->cri_alg == CRYPTO_SHA1_HMAC ||
++		    c->cri_alg == CRYPTO_NULL_HMAC) {
++			if (macini)
++				return EINVAL;
++			macini = c;
++		} else if (c->cri_alg == CRYPTO_DES_CBC ||
++		    c->cri_alg == CRYPTO_3DES_CBC ||
++		    c->cri_alg == CRYPTO_AES_CBC ||
++		    c->cri_alg == CRYPTO_NULL_CBC) {
++			if (encini)
++				return EINVAL;
++			encini = c;
++		} else {
++			DPRINTF("UNKNOWN c->cri_alg %d\n", encini->cri_alg);
++			return EINVAL;
++		}
++	}
++	if (encini == NULL && macini == NULL)
++		return EINVAL;
++	if (encini) {	
++		/* validate key length */
++		switch (encini->cri_alg) {
++		case CRYPTO_DES_CBC:
++			if (encini->cri_klen != 64)
++				return EINVAL;
++			break;
++		case CRYPTO_3DES_CBC:
++			if (encini->cri_klen != 192) {
++				return EINVAL;
++			}
++			break;
++		case CRYPTO_AES_CBC:
++			if (encini->cri_klen != 128 &&
++			    encini->cri_klen != 192 &&
++			    encini->cri_klen != 256)
++				return EINVAL;
++			break;
++		default:
++			DPRINTF("UNKNOWN encini->cri_alg %d\n", 
++				encini->cri_alg);
++			return EINVAL;
++		}
++	}
++
++	if (sc->sc_sessions == NULL) {
++		ses = sc->sc_sessions = (struct talitos_session *)
++			kmalloc(sizeof(struct talitos_session), SLAB_ATOMIC);
++		if (ses == NULL)
++			return ENOMEM;
++		memset(ses, 0, sizeof(struct talitos_session));
++		sesn = 0;
++		sc->sc_nsessions = 1;
++	} else {
++		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
++			if (sc->sc_sessions[sesn].ses_used == 0) {
++				ses = &sc->sc_sessions[sesn];
++				break;
++			}
++		}
++
++		if (ses == NULL) {
++			/* allocating session */
++			sesn = sc->sc_nsessions;
++			ses = (struct talitos_session *) kmalloc(
++				(sesn + 1) * sizeof(struct talitos_session), 
++				SLAB_ATOMIC);
++			if (ses == NULL)
++				return ENOMEM;
++			memset(ses, 0,
++				(sesn + 1) * sizeof(struct talitos_session));
++			memcpy(ses, sc->sc_sessions, 
++				sesn * sizeof(struct talitos_session));
++			memset(sc->sc_sessions, 0,
++				sesn * sizeof(struct talitos_session));
++			kfree(sc->sc_sessions);
++			sc->sc_sessions = ses;
++			ses = &sc->sc_sessions[sesn];
++			sc->sc_nsessions++;
++		}
++	}
++
++	ses->ses_used = 1;
++
++	if (encini) {
++		/* get an IV */
++		/* XXX may read fewer than requested */
++		read_random(ses->ses_iv, sizeof(ses->ses_iv));
++
++		ses->ses_klen = (encini->cri_klen + 7) / 8;
++		memcpy(ses->ses_key, encini->cri_key, ses->ses_klen);
++		if (macini) {
++			/* doing hash on top of cipher */
++			ses->ses_hmac_len = (macini->cri_klen + 7) / 8;
++			memcpy(ses->ses_hmac, macini->cri_key,
++				ses->ses_hmac_len);
++		}
++	} else if (macini) {
++		/* doing hash */
++		ses->ses_klen = (macini->cri_klen + 7) / 8;
++		memcpy(ses->ses_key, macini->cri_key, ses->ses_klen);
++	}
++
++	/* back compat way of determining MSC result len */
++	if (macini) {
++		ses->ses_mlen = macini->cri_mlen;
++		if (ses->ses_mlen == 0) {
++			if (macini->cri_alg == CRYPTO_MD5_HMAC)
++				ses->ses_mlen = MD5_HASH_LEN;
++			else
++				ses->ses_mlen = SHA1_HASH_LEN;
++		}
++	}
++
++	/* really should make up a template td here, 
++	 * and only fill things like i/o and direction in process() */
++
++	/* assign session ID */
++	*sidp = TALITOS_SID(sc->sc_num, sesn);
++	return 0;
++}
++
++/*
++ * Deallocate a session.
++ */
++static int
++talitos_freesession(device_t dev, u_int64_t tid)
++{
++	struct talitos_softc *sc = device_get_softc(dev);
++	int session, ret;
++	u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
++
++	if (sc == NULL)
++		return EINVAL;
++	session = TALITOS_SESSION(sid);
++	if (session < sc->sc_nsessions) {
++		memset(&sc->sc_sessions[session], 0,
++			sizeof(sc->sc_sessions[session]));
++		ret = 0;
++	} else
++		ret = EINVAL;
++	return ret;
++}
++
++/*
++ * launch device processing - it will come back with done notification 
++ * in the form of an interrupt and/or HDR_DONE_BITS in header 
++ */
++static int 
++talitos_submit(
++	struct talitos_softc *sc,
++	struct talitos_desc *td,
++	int chsel)
++{
++	u_int32_t v;
++
++	v = dma_map_single(NULL, td, sizeof(*td), DMA_TO_DEVICE);
++	talitos_write(sc->sc_base_addr + 
++		chsel*TALITOS_CH_OFFSET + TALITOS_CH_FF, 0);
++	talitos_write(sc->sc_base_addr + 
++		chsel*TALITOS_CH_OFFSET + TALITOS_CH_FF_HI, v);
++	return 0;
++}
++
++static int
++talitos_process(device_t dev, struct cryptop *crp, int hint)
++{
++	int i, err = 0, ivsize;
++	struct talitos_softc *sc = device_get_softc(dev);
++	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
++	caddr_t iv;
++	struct talitos_session *ses;
++	struct talitos_desc *td;
++	unsigned long flags;
++	/* descriptor mappings */
++	int hmac_key, hmac_data, cipher_iv, cipher_key, 
++		in_fifo, out_fifo, cipher_iv_out;
++	static int chsel = -1;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
++		return EINVAL;
++	}
++	crp->crp_etype = 0;
++	if (TALITOS_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
++		return EINVAL;
++	}
++
++	ses = &sc->sc_sessions[TALITOS_SESSION(crp->crp_sid)];
++
++        /* enter the channel scheduler */ 
++	spin_lock_irqsave(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
++
++	/* reuse channel that already had/has requests for the required EU */
++	for (i = 0; i < sc->sc_num_channels; i++) {
++		if (sc->sc_chnlastalg[i] == crp->crp_desc->crd_alg)
++			break;
++	}
++	if (i == sc->sc_num_channels) {
++		/*
++		 * haven't seen this algo the last sc_num_channels or more
++		 * use round robin in this case
++	 	 * nb: sc->sc_num_channels must be power of 2 
++		 */
++		chsel = (chsel + 1) & (sc->sc_num_channels - 1);
++	} else {
++		/*
++		 * matches channel with same target execution unit; 
++		 * use same channel in this case
++		 */
++		chsel = i;
++	}
++	sc->sc_chnlastalg[chsel] = crp->crp_desc->crd_alg;
++
++        /* release the channel scheduler lock */ 
++	spin_unlock_irqrestore(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
++
++	/* acquire the selected channel fifo lock */
++	spin_lock_irqsave(&sc->sc_chnfifolock[chsel], flags);
++
++	/* find and reserve next available descriptor-cryptop pair */
++	for (i = 0; i < sc->sc_chfifo_len; i++) {
++		if (sc->sc_chnfifo[chsel][i].cf_desc.hdr == 0) {
++			/* 
++			 * ensure correct descriptor formation by
++			 * avoiding inadvertently setting "optional" entries
++			 * e.g. not using "optional" dptr2 for MD/HMAC descs
++			 */
++			memset(&sc->sc_chnfifo[chsel][i].cf_desc,
++				0, sizeof(*td));
++			/* reserve it with done notification request bit */
++			sc->sc_chnfifo[chsel][i].cf_desc.hdr |= 
++				TALITOS_DONE_NOTIFY;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&sc->sc_chnfifolock[chsel], flags);
++
++	if (i == sc->sc_chfifo_len) {
++		/* fifo full */
++		err = ERESTART;
++		goto errout;
++	}
++	
++	td = &sc->sc_chnfifo[chsel][i].cf_desc;
++	sc->sc_chnfifo[chsel][i].cf_crp = crp;
++
++	crd1 = crp->crp_desc;
++	if (crd1 == NULL) {
++		err = EINVAL;
++		goto errout;
++	}
++	crd2 = crd1->crd_next;
++	/* prevent compiler warning */
++	hmac_key = 0;
++	hmac_data = 0;
++	if (crd2 == NULL) {
++		td->hdr |= TD_TYPE_COMMON_NONSNOOP_NO_AFEU;
++		/* assign descriptor dword ptr mappings for this desc. type */
++		cipher_iv = 1;
++		cipher_key = 2;
++		in_fifo = 3;
++		cipher_iv_out = 5;
++		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
++		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
++		    crd1->crd_alg == CRYPTO_SHA1 ||
++		    crd1->crd_alg == CRYPTO_MD5) {
++			out_fifo = 5;
++			maccrd = crd1;
++			enccrd = NULL;
++		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
++		    crd1->crd_alg == CRYPTO_3DES_CBC ||
++		    crd1->crd_alg == CRYPTO_AES_CBC ||
++		    crd1->crd_alg == CRYPTO_ARC4) {
++			out_fifo = 4;
++			maccrd = NULL;
++			enccrd = crd1;
++		} else {
++			DPRINTF("UNKNOWN crd1->crd_alg %d\n", crd1->crd_alg);
++			err = EINVAL;
++			goto errout;
++		}
++	} else {
++		if (sc->sc_desc_types & TALITOS_HAS_DT_IPSEC_ESP) {
++			td->hdr |= TD_TYPE_IPSEC_ESP;
++		} else {
++			DPRINTF("unimplemented: multiple descriptor ipsec\n");
++			err = EINVAL;
++			goto errout;
++		}
++		/* assign descriptor dword ptr mappings for this desc. type */
++		hmac_key = 0;
++		hmac_data = 1;
++		cipher_iv = 2;
++		cipher_key = 3;
++		in_fifo = 4;
++		out_fifo = 5;
++		cipher_iv_out = 6;
++		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
++                     crd1->crd_alg == CRYPTO_SHA1_HMAC ||
++                     crd1->crd_alg == CRYPTO_MD5 ||
++                     crd1->crd_alg == CRYPTO_SHA1) &&
++		    (crd2->crd_alg == CRYPTO_DES_CBC ||
++		     crd2->crd_alg == CRYPTO_3DES_CBC ||
++		     crd2->crd_alg == CRYPTO_AES_CBC ||
++		     crd2->crd_alg == CRYPTO_ARC4) &&
++		    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
++			maccrd = crd1;
++			enccrd = crd2;
++		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
++		     crd1->crd_alg == CRYPTO_ARC4 ||
++		     crd1->crd_alg == CRYPTO_3DES_CBC ||
++		     crd1->crd_alg == CRYPTO_AES_CBC) &&
++		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
++                     crd2->crd_alg == CRYPTO_SHA1_HMAC ||
++                     crd2->crd_alg == CRYPTO_MD5 ||
++                     crd2->crd_alg == CRYPTO_SHA1) &&
++		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
++			enccrd = crd1;
++			maccrd = crd2;
++		} else {
++			/* We cannot order the SEC as requested */
++			printk("%s: cannot do the order\n",
++					device_get_nameunit(sc->sc_cdev));
++			err = EINVAL;
++			goto errout;
++		}
++	}
++	/* assign in_fifo and out_fifo based on input/output struct type */
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		/* using SKB buffers */
++		struct sk_buff *skb = (struct sk_buff *)crp->crp_buf;
++		if (skb_shinfo(skb)->nr_frags) {
++			printk("%s: skb frags unimplemented\n",
++					device_get_nameunit(sc->sc_cdev));
++			err = EINVAL;
++			goto errout;
++		}
++		td->ptr[in_fifo].ptr = dma_map_single(NULL, skb->data, 
++			skb->len, DMA_TO_DEVICE);
++		td->ptr[in_fifo].len = skb->len;
++		td->ptr[out_fifo].ptr = dma_map_single(NULL, skb->data, 
++			skb->len, DMA_TO_DEVICE);
++		td->ptr[out_fifo].len = skb->len;
++		td->ptr[hmac_data].ptr = dma_map_single(NULL, skb->data,
++			skb->len, DMA_TO_DEVICE);
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		/* using IOV buffers */
++		struct uio *uiop = (struct uio *)crp->crp_buf;
++		if (uiop->uio_iovcnt > 1) {
++			printk("%s: iov frags unimplemented\n",
++					device_get_nameunit(sc->sc_cdev));
++			err = EINVAL;
++			goto errout;
++		}
++		td->ptr[in_fifo].ptr = dma_map_single(NULL,
++			uiop->uio_iov->iov_base, crp->crp_ilen, DMA_TO_DEVICE);
++		td->ptr[in_fifo].len = crp->crp_ilen;
++		/* crp_olen is never set; always use crp_ilen */
++		td->ptr[out_fifo].ptr = dma_map_single(NULL,
++			uiop->uio_iov->iov_base,
++			crp->crp_ilen, DMA_TO_DEVICE);
++		td->ptr[out_fifo].len = crp->crp_ilen;
++	} else {
++		/* using contig buffers */
++		td->ptr[in_fifo].ptr = dma_map_single(NULL,
++			crp->crp_buf, crp->crp_ilen, DMA_TO_DEVICE);
++		td->ptr[in_fifo].len = crp->crp_ilen;
++		td->ptr[out_fifo].ptr = dma_map_single(NULL,
++			crp->crp_buf, crp->crp_ilen, DMA_TO_DEVICE);
++		td->ptr[out_fifo].len = crp->crp_ilen;
++	}
++	if (enccrd) {
++		switch (enccrd->crd_alg) {
++		case CRYPTO_3DES_CBC:
++			td->hdr |= TALITOS_MODE0_DEU_3DES;
++			/* FALLTHROUGH */
++		case CRYPTO_DES_CBC:
++			td->hdr |= TALITOS_SEL0_DEU
++				|  TALITOS_MODE0_DEU_CBC;
++			if (enccrd->crd_flags & CRD_F_ENCRYPT)
++				td->hdr |= TALITOS_MODE0_DEU_ENC;
++			ivsize = 2*sizeof(u_int32_t);
++			DPRINTF("%cDES ses %d ch %d len %d\n",
++				(td->hdr & TALITOS_MODE0_DEU_3DES)?'3':'1',
++				(u32)TALITOS_SESSION(crp->crp_sid),
++				chsel, td->ptr[in_fifo].len);
++			break;
++		case CRYPTO_AES_CBC:
++			td->hdr |= TALITOS_SEL0_AESU
++				|  TALITOS_MODE0_AESU_CBC;
++			if (enccrd->crd_flags & CRD_F_ENCRYPT)
++				td->hdr |= TALITOS_MODE0_AESU_ENC;
++			ivsize = 4*sizeof(u_int32_t);
++			DPRINTF("AES  ses %d ch %d len %d\n",
++				(u32)TALITOS_SESSION(crp->crp_sid),
++				chsel, td->ptr[in_fifo].len);
++			break;
++		default:
++			printk("%s: unimplemented enccrd->crd_alg %d\n",
++					device_get_nameunit(sc->sc_cdev), enccrd->crd_alg);
++			err = EINVAL;
++			goto errout;
++		}
++		/*
++		 * Setup encrypt/decrypt state.  When using basic ops
++		 * we can't use an inline IV because hash/crypt offset
++		 * must be from the end of the IV to the start of the
++		 * crypt data and this leaves out the preceding header
++		 * from the hash calculation.  Instead we place the IV
++		 * in the state record and set the hash/crypt offset to
++		 * copy both the header+IV.
++		 */
++		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
++			td->hdr |= TALITOS_DIR_OUTBOUND; 
++			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
++				iv = enccrd->crd_iv;
++			else
++				iv = (caddr_t) ses->ses_iv;
++			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
++				crypto_copyback(crp->crp_flags, crp->crp_buf,
++				    enccrd->crd_inject, ivsize, iv);
++			}
++		} else {
++			td->hdr |= TALITOS_DIR_INBOUND; 
++			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
++				iv = enccrd->crd_iv;
++				bcopy(enccrd->crd_iv, iv, ivsize);
++			} else {
++				iv = (caddr_t) ses->ses_iv;
++				crypto_copydata(crp->crp_flags, crp->crp_buf,
++				    enccrd->crd_inject, ivsize, iv);
++			}
++		}
++		td->ptr[cipher_iv].ptr = dma_map_single(NULL, iv, ivsize, 
++			DMA_TO_DEVICE);
++		td->ptr[cipher_iv].len = ivsize;
++		/*
++		 * we don't need the cipher iv out length/pointer
++		 * field to do ESP IPsec. Therefore we set the len field as 0,
++		 * which tells the SEC not to do anything with this len/ptr
++		 * field. Previously, when length/pointer as pointing to iv,
++		 * it gave us corruption of packets.
++		 */
++		td->ptr[cipher_iv_out].len = 0;
++	}
++	if (enccrd && maccrd) {
++		/* this is ipsec only for now */
++		td->hdr |= TALITOS_SEL1_MDEU
++			|  TALITOS_MODE1_MDEU_INIT
++			|  TALITOS_MODE1_MDEU_PAD;
++		switch (maccrd->crd_alg) {
++			case	CRYPTO_MD5:	
++				td->hdr |= TALITOS_MODE1_MDEU_MD5;
++				break;
++			case	CRYPTO_MD5_HMAC:	
++				td->hdr |= TALITOS_MODE1_MDEU_MD5_HMAC;
++				break;
++			case	CRYPTO_SHA1:	
++				td->hdr |= TALITOS_MODE1_MDEU_SHA1;
++				break;
++			case	CRYPTO_SHA1_HMAC:	
++				td->hdr |= TALITOS_MODE1_MDEU_SHA1_HMAC;
++				break;
++			default:
++				/* We cannot order the SEC as requested */
++				printk("%s: cannot do the order\n",
++						device_get_nameunit(sc->sc_cdev));
++				err = EINVAL;
++				goto errout;
++		}
++		if ((maccrd->crd_alg == CRYPTO_MD5_HMAC) ||
++		   (maccrd->crd_alg == CRYPTO_SHA1_HMAC)) {
++			/*
++			 * The offset from hash data to the start of
++			 * crypt data is the difference in the skips.
++			 */
++			/* ipsec only for now */
++			td->ptr[hmac_key].ptr = dma_map_single(NULL, 
++				ses->ses_hmac, ses->ses_hmac_len, DMA_TO_DEVICE);
++			td->ptr[hmac_key].len = ses->ses_hmac_len;
++			td->ptr[in_fifo].ptr  += enccrd->crd_skip;
++			td->ptr[in_fifo].len  =  enccrd->crd_len;
++			td->ptr[out_fifo].ptr += enccrd->crd_skip;
++			td->ptr[out_fifo].len =  enccrd->crd_len;
++			/* bytes of HMAC to postpend to ciphertext */
++			td->ptr[out_fifo].extent =  ses->ses_mlen;
++			td->ptr[hmac_data].ptr += maccrd->crd_skip; 
++			td->ptr[hmac_data].len = enccrd->crd_skip - maccrd->crd_skip;
++		}
++		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
++			printk("%s: CRD_F_KEY_EXPLICIT unimplemented\n",
++					device_get_nameunit(sc->sc_cdev));
++		}
++	}
++	if (!enccrd && maccrd) {
++		/* single MD5 or SHA */
++		td->hdr |= TALITOS_SEL0_MDEU
++				|  TALITOS_MODE0_MDEU_INIT
++				|  TALITOS_MODE0_MDEU_PAD;
++		switch (maccrd->crd_alg) {
++			case	CRYPTO_MD5:	
++				td->hdr |= TALITOS_MODE0_MDEU_MD5;
++				DPRINTF("MD5  ses %d ch %d len %d\n",
++					(u32)TALITOS_SESSION(crp->crp_sid), 
++					chsel, td->ptr[in_fifo].len);
++				break;
++			case	CRYPTO_MD5_HMAC:	
++				td->hdr |= TALITOS_MODE0_MDEU_MD5_HMAC;
++				break;
++			case	CRYPTO_SHA1:	
++				td->hdr |= TALITOS_MODE0_MDEU_SHA1;
++				DPRINTF("SHA1 ses %d ch %d len %d\n",
++					(u32)TALITOS_SESSION(crp->crp_sid), 
++					chsel, td->ptr[in_fifo].len);
++				break;
++			case	CRYPTO_SHA1_HMAC:	
++				td->hdr |= TALITOS_MODE0_MDEU_SHA1_HMAC;
++				break;
++			default:
++				/* We cannot order the SEC as requested */
++				DPRINTF("cannot do the order\n");
++				err = EINVAL;
++				goto errout;
++		}
++
++		if (crp->crp_flags & CRYPTO_F_IOV)
++			td->ptr[out_fifo].ptr += maccrd->crd_inject;
++
++		if ((maccrd->crd_alg == CRYPTO_MD5_HMAC) ||
++		   (maccrd->crd_alg == CRYPTO_SHA1_HMAC)) {
++			td->ptr[hmac_key].ptr = dma_map_single(NULL, 
++				ses->ses_hmac, ses->ses_hmac_len, 
++				DMA_TO_DEVICE);
++			td->ptr[hmac_key].len = ses->ses_hmac_len;
++		}
++	} 
++	else {
++		/* using process key (session data has duplicate) */
++		td->ptr[cipher_key].ptr = dma_map_single(NULL, 
++			enccrd->crd_key, (enccrd->crd_klen + 7) / 8, 
++			DMA_TO_DEVICE);
++		td->ptr[cipher_key].len = (enccrd->crd_klen + 7) / 8;
++	}
++	/* descriptor complete - GO! */
++	return talitos_submit(sc, td, chsel);
++
++errout:
++	if (err != ERESTART) {
++		crp->crp_etype = err;
++		crypto_done(crp);
++	}
++	return err;
++}
++
++/* go through all channels descriptors, notifying OCF what has 
++ * _and_hasn't_ successfully completed and reset the device 
++ * (otherwise it's up to decoding desc hdrs!)
++ */
++static void talitos_errorprocessing(struct talitos_softc *sc)
++{
++	unsigned long flags;
++	int i, j;
++
++	/* disable further scheduling until under control */
++	spin_lock_irqsave(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
++
++	if (debug) dump_talitos_status(sc);
++	/* go through descriptors, try and salvage those successfully done, 
++	 * and EIO those that weren't
++	 */
++	for (i = 0; i < sc->sc_num_channels; i++) {
++		spin_lock_irqsave(&sc->sc_chnfifolock[i], flags);
++		for (j = 0; j < sc->sc_chfifo_len; j++) {
++			if (sc->sc_chnfifo[i][j].cf_desc.hdr) {
++				if ((sc->sc_chnfifo[i][j].cf_desc.hdr 
++					& TALITOS_HDR_DONE_BITS) 
++					!= TALITOS_HDR_DONE_BITS) {
++					/* this one didn't finish */
++					/* signify in crp->etype */
++					sc->sc_chnfifo[i][j].cf_crp->crp_etype 
++						= EIO;
++				}
++			} else
++				continue; /* free entry */
++			/* either way, notify ocf */
++			crypto_done(sc->sc_chnfifo[i][j].cf_crp);
++			/* and tag it available again
++			 *
++			 * memset to ensure correct descriptor formation by
++			 * avoiding inadvertently setting "optional" entries
++			 * e.g. not using "optional" dptr2 MD/HMAC processing
++			 */
++			memset(&sc->sc_chnfifo[i][j].cf_desc,
++				0, sizeof(struct talitos_desc));
++		}
++		spin_unlock_irqrestore(&sc->sc_chnfifolock[i], flags);
++	}
++	/* reset and initialize the SEC h/w device */
++	talitos_reset_device(sc);
++	talitos_init_device(sc);
++#ifdef CONFIG_OCF_RANDOMHARVEST
++	if (sc->sc_exec_units & TALITOS_HAS_EU_RNG)
++		talitos_rng_init(sc);
++#endif
++
++	/* Okay. Stand by. */
++	spin_unlock_irqrestore(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
++
++	return;
++}
++
++/* go through all channels descriptors, notifying OCF what's been done */
++static void talitos_doneprocessing(struct talitos_softc *sc)
++{
++	unsigned long flags;
++	int i, j;
++
++	/* go through descriptors looking for done bits */
++	for (i = 0; i < sc->sc_num_channels; i++) {
++		spin_lock_irqsave(&sc->sc_chnfifolock[i], flags);
++		for (j = 0; j < sc->sc_chfifo_len; j++) {
++			/* descriptor has done bits set? */
++			if ((sc->sc_chnfifo[i][j].cf_desc.hdr 
++				& TALITOS_HDR_DONE_BITS) 
++				== TALITOS_HDR_DONE_BITS) {
++				/* notify ocf */
++				crypto_done(sc->sc_chnfifo[i][j].cf_crp);
++				/* and tag it available again
++				 *
++				 * memset to ensure correct descriptor formation by
++				 * avoiding inadvertently setting "optional" entries
++				 * e.g. not using "optional" dptr2 MD/HMAC processing
++				 */
++				memset(&sc->sc_chnfifo[i][j].cf_desc,
++					0, sizeof(struct talitos_desc));
++			}
++		}
++		spin_unlock_irqrestore(&sc->sc_chnfifolock[i], flags);
++	}
++	return;
++}
++
++static irqreturn_t
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++talitos_intr(int irq, void *arg)
++#else
++talitos_intr(int irq, void *arg, struct pt_regs *regs)
++#endif
++{
++	struct talitos_softc *sc = arg;
++	u_int32_t v, v_hi;
++	
++	/* ack */
++	v = talitos_read(sc->sc_base_addr + TALITOS_ISR);
++	v_hi = talitos_read(sc->sc_base_addr + TALITOS_ISR_HI);
++	talitos_write(sc->sc_base_addr + TALITOS_ICR, v);
++	talitos_write(sc->sc_base_addr + TALITOS_ICR_HI, v_hi);
++
++	if (unlikely(v & TALITOS_ISR_ERROR)) {
++		/* Okay, Houston, we've had a problem here. */
++		printk(KERN_DEBUG "%s: got error interrupt - ISR 0x%08x_%08x\n",
++				device_get_nameunit(sc->sc_cdev), v, v_hi);
++		talitos_errorprocessing(sc);
++	} else
++	if (likely(v & TALITOS_ISR_DONE)) {
++		talitos_doneprocessing(sc);
++	}
++	return IRQ_HANDLED;
++}
++
++/*
++ * Initialize registers we need to touch only once.
++ */
++static void
++talitos_init_device(struct talitos_softc *sc)
++{
++	u_int32_t v;
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	/* init all channels */
++	for (i = 0; i < sc->sc_num_channels; i++) {
++		v = talitos_read(sc->sc_base_addr + 
++			i*TALITOS_CH_OFFSET + TALITOS_CH_CCCR_HI);
++		v |= TALITOS_CH_CCCR_HI_CDWE
++		  |  TALITOS_CH_CCCR_HI_CDIE;  /* invoke interrupt if done */
++		talitos_write(sc->sc_base_addr + 
++			i*TALITOS_CH_OFFSET + TALITOS_CH_CCCR_HI, v);
++	}
++	/* enable all interrupts */
++	v = talitos_read(sc->sc_base_addr + TALITOS_IMR);
++	v |= TALITOS_IMR_ALL;
++	talitos_write(sc->sc_base_addr + TALITOS_IMR, v);
++	v = talitos_read(sc->sc_base_addr + TALITOS_IMR_HI);
++	v |= TALITOS_IMR_HI_ERRONLY;
++	talitos_write(sc->sc_base_addr + TALITOS_IMR_HI, v);
++	return;
++}
++
++/*
++ * set the master reset bit on the device.
++ */
++static void
++talitos_reset_device_master(struct talitos_softc *sc)
++{
++	u_int32_t v;
++
++	/* Reset the device by writing 1 to MCR:SWR and waiting 'til cleared */
++	v = talitos_read(sc->sc_base_addr + TALITOS_MCR);
++	talitos_write(sc->sc_base_addr + TALITOS_MCR, v | TALITOS_MCR_SWR);
++
++	while (talitos_read(sc->sc_base_addr + TALITOS_MCR) & TALITOS_MCR_SWR)
++		cpu_relax();
++
++	return;
++}
++
++/*
++ * Resets the device.  Values in the registers are left as is
++ * from the reset (i.e. initial values are assigned elsewhere).
++ */
++static void
++talitos_reset_device(struct talitos_softc *sc)
++{
++	u_int32_t v;
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	/*
++	 * Master reset
++	 * errata documentation: warning: certain SEC interrupts 
++	 * are not fully cleared by writing the MCR:SWR bit, 
++	 * set bit twice to completely reset 
++	 */
++	talitos_reset_device_master(sc);	/* once */
++	talitos_reset_device_master(sc);	/* and once again */
++	
++	/* reset all channels */
++	for (i = 0; i < sc->sc_num_channels; i++) {
++		v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
++			TALITOS_CH_CCCR);
++		talitos_write(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
++			TALITOS_CH_CCCR, v | TALITOS_CH_CCCR_RESET);
++	}
++}
++
++/* Set up the crypto device structure, private data,
++ * and anything else we need before we start */
++#ifdef CONFIG_PPC_MERGE
++static int talitos_probe(struct of_device *ofdev, const struct of_device_id *match)
++#else
++static int talitos_probe(struct platform_device *pdev)
++#endif
++{
++	struct talitos_softc *sc = NULL;
++	struct resource *r;
++#ifdef CONFIG_PPC_MERGE
++	struct device *device = &ofdev->dev;
++	struct device_node *np = ofdev->node;
++	const unsigned int *prop;
++#endif
++	static int num_chips = 0;
++	int rc;
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++
++	sc = (struct talitos_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
++	if (!sc)
++		return -ENOMEM;
++	memset(sc, 0, sizeof(*sc));
++
++	softc_device_init(sc, DRV_NAME, num_chips, talitos_methods);
++
++	sc->sc_irq = -1;
++	sc->sc_cid = -1;
++#ifdef CONFIG_PPC_MERGE
++	sc->sc_dev = device;
++#else
++	sc->sc_dev = pdev;
++#endif
++	sc->sc_num = num_chips++;
++
++#ifdef CONFIG_PPC_MERGE
++	dev_set_drvdata(device, sc);
++#else
++	platform_set_drvdata(sc->sc_dev, sc);
++#endif
++
++	/* get the irq line */
++#ifdef CONFIG_PPC_MERGE
++	err = of_address_to_resource(np, 0, &res);
++	if (err)
++		return -EINVAL;
++
++	sc->sc_irq = irq_of_parse_and_map(np, 0);
++#else
++	/* get a pointer to the register memory */
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++	sc->sc_irq = platform_get_irq(pdev, 0);
++#endif
++	rc = request_irq(sc->sc_irq, talitos_intr, 0,
++			device_get_nameunit(sc->sc_cdev), sc);
++	if (rc) {
++		printk(KERN_ERR "%s: failed to hook irq %d\n", 
++				device_get_nameunit(sc->sc_cdev), sc->sc_irq);
++		sc->sc_irq = -1;
++		goto out;
++	}
++
++	sc->sc_base_addr = (ocf_iomem_t) ioremap(r->start, (r->end - r->start));
++	if (!sc->sc_base_addr) {
++		printk(KERN_ERR "%s: failed to ioremap\n",
++				device_get_nameunit(sc->sc_cdev));
++		goto out;
++	}
++
++	/* figure out our SEC's properties and capabilities */
++	sc->sc_chiprev = (u64)talitos_read(sc->sc_base_addr + TALITOS_ID) << 32
++		 | talitos_read(sc->sc_base_addr + TALITOS_ID_HI);
++	DPRINTF("sec id 0x%llx\n", sc->sc_chiprev);
++
++#ifdef CONFIG_PPC_MERGE
++	/* get SEC properties from device tree, defaulting to SEC 2.0 */
++
++	prop = of_get_property(np, "num-channels", NULL);
++	sc->sc_num_channels = prop ? *prop : TALITOS_NCHANNELS_SEC_2_0;
++
++	prop = of_get_property(np, "channel-fifo-len", NULL);
++	sc->sc_chfifo_len = prop ? *prop : TALITOS_CHFIFOLEN_SEC_2_0;
++
++	prop = of_get_property(np, "exec-units-mask", NULL);
++	sc->sc_exec_units = prop ? *prop : TALITOS_HAS_EUS_SEC_2_0;
++
++	prop = of_get_property(np, "descriptor-types-mask", NULL);
++	sc->sc_desc_types = prop ? *prop : TALITOS_HAS_DESCTYPES_SEC_2_0;
++#else
++	/* bulk should go away with openfirmware flat device tree support */
++	if (sc->sc_chiprev & TALITOS_ID_SEC_2_0) {
++		sc->sc_num_channels = TALITOS_NCHANNELS_SEC_2_0;
++		sc->sc_chfifo_len = TALITOS_CHFIFOLEN_SEC_2_0;
++		sc->sc_exec_units = TALITOS_HAS_EUS_SEC_2_0;
++		sc->sc_desc_types = TALITOS_HAS_DESCTYPES_SEC_2_0;
++	} else {
++		printk(KERN_ERR "%s: failed to id device\n",
++				device_get_nameunit(sc->sc_cdev));
++		goto out;
++	}
++#endif
++
++	/* + 1 is for the meta-channel lock used by the channel scheduler */
++	sc->sc_chnfifolock = (spinlock_t *) kmalloc(
++		(sc->sc_num_channels + 1) * sizeof(spinlock_t), GFP_KERNEL);
++	if (!sc->sc_chnfifolock)
++		goto out;
++	for (i = 0; i < sc->sc_num_channels + 1; i++) {
++		spin_lock_init(&sc->sc_chnfifolock[i]);
++	}
++
++	sc->sc_chnlastalg = (int *) kmalloc(
++		sc->sc_num_channels * sizeof(int), GFP_KERNEL);
++	if (!sc->sc_chnlastalg)
++		goto out;
++	memset(sc->sc_chnlastalg, 0, sc->sc_num_channels * sizeof(int));
++
++	sc->sc_chnfifo = (struct desc_cryptop_pair **) kmalloc(
++		sc->sc_num_channels * sizeof(struct desc_cryptop_pair *), 
++		GFP_KERNEL);
++	if (!sc->sc_chnfifo)
++		goto out;
++	for (i = 0; i < sc->sc_num_channels; i++) {
++		sc->sc_chnfifo[i] = (struct desc_cryptop_pair *) kmalloc(
++			sc->sc_chfifo_len * sizeof(struct desc_cryptop_pair), 
++			GFP_KERNEL);
++		if (!sc->sc_chnfifo[i])
++			goto out;
++		memset(sc->sc_chnfifo[i], 0, 
++			sc->sc_chfifo_len * sizeof(struct desc_cryptop_pair));
++	}
++
++	/* reset and initialize the SEC h/w device */
++	talitos_reset_device(sc);
++	talitos_init_device(sc);
++
++	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
++	if (sc->sc_cid < 0) {
++		printk(KERN_ERR "%s: could not get crypto driver id\n",
++				device_get_nameunit(sc->sc_cdev));
++		goto out;
++	}
++
++	/* register algorithms with the framework */
++	printk("%s:", device_get_nameunit(sc->sc_cdev));
++
++	if (sc->sc_exec_units & TALITOS_HAS_EU_RNG)  {
++		printk(" rng");
++#ifdef CONFIG_OCF_RANDOMHARVEST
++		talitos_rng_init(sc);
++		crypto_rregister(sc->sc_cid, talitos_read_random, sc);
++#endif
++	}
++	if (sc->sc_exec_units & TALITOS_HAS_EU_DEU) {
++		printk(" des/3des");
++		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
++		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
++	}
++	if (sc->sc_exec_units & TALITOS_HAS_EU_AESU) {
++		printk(" aes");
++		crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
++	}
++	if (sc->sc_exec_units & TALITOS_HAS_EU_MDEU) {
++		printk(" md5");
++		crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
++		/* HMAC support only with IPsec for now */
++		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
++		printk(" sha1");
++		crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
++		/* HMAC support only with IPsec for now */
++		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
++	}
++	printk("\n");
++	return 0;
++
++out:
++#ifndef CONFIG_PPC_MERGE
++	talitos_remove(pdev);
++#endif
++	return -ENOMEM;
++}
++
++static int talitos_remove(struct platform_device *pdev)
++{
++	struct talitos_softc *sc = platform_get_drvdata(pdev);
++	int i;
++
++	DPRINTF("%s()\n", __FUNCTION__);
++	if (sc->sc_cid >= 0)
++		crypto_unregister_all(sc->sc_cid);
++	if (sc->sc_chnfifo) {
++		for (i = 0; i < sc->sc_num_channels; i++)
++			if (sc->sc_chnfifo[i])
++				kfree(sc->sc_chnfifo[i]);
++		kfree(sc->sc_chnfifo);
++	}
++	if (sc->sc_chnlastalg)
++		kfree(sc->sc_chnlastalg);
++	if (sc->sc_chnfifolock)
++		kfree(sc->sc_chnfifolock);
++	if (sc->sc_irq != -1)
++		free_irq(sc->sc_irq, sc);
++	if (sc->sc_base_addr)
++		iounmap((void *) sc->sc_base_addr);
++	kfree(sc);
++	return 0;
++}
++
++#ifdef CONFIG_PPC_MERGE
++static struct of_device_id talitos_match[] = {
++	{
++		.type = "crypto",
++		.compatible = "talitos",
++	},
++	{},
++};
++
++MODULE_DEVICE_TABLE(of, talitos_match);
++
++static struct of_platform_driver talitos_driver = {
++	.name		= DRV_NAME,
++	.match_table	= talitos_match,
++	.probe		= talitos_probe,
++	.remove		= talitos_remove,
++};
++
++static int __init talitos_init(void)
++{
++	return of_platform_driver_register(&talitos_driver);
++}
++
++static void __exit talitos_exit(void)
++{
++	of_platform_driver_unregister(&talitos_driver);
++}
++#else
++/* Structure for a platform device driver */
++static struct platform_driver talitos_driver = {
++	.probe = talitos_probe,
++	.remove = talitos_remove,
++	.driver = {
++		.name = "fsl-sec2",
++	}
++};
++
++static int __init talitos_init(void)
++{
++	return platform_driver_register(&talitos_driver);
++}
++
++static void __exit talitos_exit(void)
++{
++	platform_driver_unregister(&talitos_driver);
++}
++#endif
++
++module_init(talitos_init);
++module_exit(talitos_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("kim.phillips@freescale.com");
++MODULE_DESCRIPTION("OCF driver for Freescale SEC (talitos)");
+diff -urN linux-2.6.23.16.old/crypto/ocf/talitos/talitos_dev.h linux-2.6.23.16/crypto/ocf/talitos/talitos_dev.h
+--- linux-2.6.23.16.old/crypto/ocf/talitos/talitos_dev.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/talitos/talitos_dev.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,277 @@
++/*
++ * Freescale SEC (talitos) device dependent data structures
++ *
++ * Copyright (c) 2006 Freescale Semiconductor, Inc.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++/* device ID register values */
++#define TALITOS_ID_SEC_2_0	0x40
++#define TALITOS_ID_SEC_2_1	0x40 /* cross ref with IP block revision reg */
++
++/*
++ * following num_channels, channel-fifo-depth, exec-unit-mask, and 
++ * descriptor-types-mask are for forward-compatibility with openfirmware
++ * flat device trees
++ */
++
++/*
++ *  num_channels : the number of channels available in each SEC version.
++ */
++
++/* n.b. this driver requires these values be a power of 2 */
++#define TALITOS_NCHANNELS_SEC_1_0	4
++#define TALITOS_NCHANNELS_SEC_1_2	1
++#define TALITOS_NCHANNELS_SEC_2_0	4
++#define TALITOS_NCHANNELS_SEC_2_01	4
++#define TALITOS_NCHANNELS_SEC_2_1	4
++#define TALITOS_NCHANNELS_SEC_2_4	4
++
++/*
++ *  channel-fifo-depth : The number of descriptor
++ *  pointers a channel fetch fifo can hold.
++ */
++#define TALITOS_CHFIFOLEN_SEC_1_0	1
++#define TALITOS_CHFIFOLEN_SEC_1_2	1
++#define TALITOS_CHFIFOLEN_SEC_2_0	24
++#define TALITOS_CHFIFOLEN_SEC_2_01	24
++#define TALITOS_CHFIFOLEN_SEC_2_1	24
++#define TALITOS_CHFIFOLEN_SEC_2_4	24
++
++/* 
++ *  exec-unit-mask : The bitmask representing what Execution Units (EUs)
++ *  are available. EU information should be encoded following the SEC's 
++ *  EU_SEL0 bitfield documentation, i.e. as follows:
++ * 
++ *    bit 31 = set if SEC permits no-EU selection (should be always set)
++ *    bit 30 = set if SEC has the ARC4 EU (AFEU)
++ *    bit 29 = set if SEC has the des/3des EU (DEU)
++ *    bit 28 = set if SEC has the message digest EU (MDEU)
++ *    bit 27 = set if SEC has the random number generator EU (RNG)
++ *    bit 26 = set if SEC has the public key EU (PKEU)
++ *    bit 25 = set if SEC has the aes EU (AESU)
++ *    bit 24 = set if SEC has the Kasumi EU (KEU)
++ * 
++ */
++#define TALITOS_HAS_EU_NONE		(1<<0)
++#define TALITOS_HAS_EU_AFEU		(1<<1)
++#define TALITOS_HAS_EU_DEU		(1<<2)
++#define TALITOS_HAS_EU_MDEU		(1<<3)
++#define TALITOS_HAS_EU_RNG		(1<<4)
++#define TALITOS_HAS_EU_PKEU		(1<<5)
++#define TALITOS_HAS_EU_AESU		(1<<6)
++#define TALITOS_HAS_EU_KEU		(1<<7)
++
++/* the corresponding masks for each SEC version */
++#define TALITOS_HAS_EUS_SEC_1_0		0x7f
++#define TALITOS_HAS_EUS_SEC_1_2		0x4d
++#define TALITOS_HAS_EUS_SEC_2_0		0x7f
++#define TALITOS_HAS_EUS_SEC_2_01	0x7f
++#define TALITOS_HAS_EUS_SEC_2_1		0xff
++#define TALITOS_HAS_EUS_SEC_2_4		0x7f
++
++/*
++ *  descriptor-types-mask : The bitmask representing what descriptors
++ *  are available. Descriptor type information should be encoded 
++ *  following the SEC's Descriptor Header Dword DESC_TYPE field 
++ *  documentation, i.e. as follows:
++ *
++ *    bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
++ *    bit 1  = set if SEC supports the ipsec_esp descriptor type
++ *    bit 2  = set if SEC supports the common_nonsnoop desc. type
++ *    bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
++ *    bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
++ *    bit 5  = set if SEC supports the srtp descriptor type
++ *    bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
++ *    bit 7  = set if SEC supports the pkeu_assemble descriptor type
++ *    bit 8  = set if SEC supports the aesu_key_expand_output desc.type
++ *    bit 9  = set if SEC supports the pkeu_ptmul descriptor type
++ *    bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
++ *    bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
++ *
++ *  ..and so on and so forth.
++ */
++#define TALITOS_HAS_DT_AESU_CTR_NONSNOOP	(1<<0)
++#define TALITOS_HAS_DT_IPSEC_ESP		(1<<1)
++#define TALITOS_HAS_DT_COMMON_NONSNOOP		(1<<2)
++
++/* the corresponding masks for each SEC version */
++#define TALITOS_HAS_DESCTYPES_SEC_2_0	0x01010ebf
++#define TALITOS_HAS_DESCTYPES_SEC_2_1	0x012b0ebf
++
++/* 
++ * a TALITOS_xxx_HI address points to the low data bits (32-63) of the register
++ */
++
++/* global register offset addresses */
++#define TALITOS_ID		0x1020
++#define TALITOS_ID_HI		0x1024
++#define TALITOS_MCR		0x1030		/* master control register */
++#define TALITOS_MCR_HI		0x1038		/* master control register */
++#define TALITOS_MCR_SWR		0x1
++#define TALITOS_IMR		0x1008		/* interrupt mask register */
++#define TALITOS_IMR_ALL		0x00010fff	/* enable all interrupts mask */
++#define TALITOS_IMR_ERRONLY	0x00010aaa	/* enable error interrupts */
++#define TALITOS_IMR_HI		0x100C		/* interrupt mask register */
++#define TALITOS_IMR_HI_ALL	0x00323333	/* enable all interrupts mask */
++#define TALITOS_IMR_HI_ERRONLY	0x00222222	/* enable error interrupts */
++#define TALITOS_ISR		0x1010		/* interrupt status register */
++#define TALITOS_ISR_ERROR	0x00010faa	/* errors mask */
++#define TALITOS_ISR_DONE	0x00000055	/* channel(s) done mask */
++#define TALITOS_ISR_HI		0x1014		/* interrupt status register */
++#define TALITOS_ICR		0x1018		/* interrupt clear register */
++#define TALITOS_ICR_HI		0x101C		/* interrupt clear register */
++
++/* channel register address stride */
++#define TALITOS_CH_OFFSET	0x100
++
++/* channel register offset addresses and bits */
++#define TALITOS_CH_CCCR		0x1108	/* Crypto-Channel Config Register */
++#define TALITOS_CH_CCCR_RESET	0x1	/* Channel Reset bit */
++#define TALITOS_CH_CCCR_HI	0x110c	/* Crypto-Channel Config Register */
++#define TALITOS_CH_CCCR_HI_CDWE	0x10	/* Channel done writeback enable bit */
++#define TALITOS_CH_CCCR_HI_NT	0x4	/* Notification type bit */
++#define TALITOS_CH_CCCR_HI_CDIE	0x2	/* Channel Done Interrupt Enable bit */
++#define TALITOS_CH_CCPSR	0x1110	/* Crypto-Channel Pointer Status Reg */
++#define TALITOS_CH_CCPSR_HI	0x1114	/* Crypto-Channel Pointer Status Reg */
++#define TALITOS_CH_FF		0x1148	/* Fetch FIFO */
++#define TALITOS_CH_FF_HI	0x114c	/* Fetch FIFO's FETCH_ADRS */
++#define TALITOS_CH_CDPR		0x1140	/* Crypto-Channel Pointer Status Reg */
++#define TALITOS_CH_CDPR_HI	0x1144	/* Crypto-Channel Pointer Status Reg */
++#define TALITOS_CH_DESCBUF	0x1180	/* (thru 11bf) Crypto-Channel 
++					 * Descriptor Buffer (debug) */
++
++/* execution unit register offset addresses and bits */
++#define TALITOS_DEUSR		0x2028	/* DEU status register */
++#define TALITOS_DEUSR_HI	0x202c	/* DEU status register */
++#define TALITOS_DEUISR		0x2030	/* DEU interrupt status register */
++#define TALITOS_DEUISR_HI	0x2034	/* DEU interrupt status register */
++#define TALITOS_DEUICR		0x2038	/* DEU interrupt control register */
++#define TALITOS_DEUICR_HI	0x203c	/* DEU interrupt control register */
++#define TALITOS_AESUISR		0x4030	/* AESU interrupt status register */
++#define TALITOS_AESUISR_HI	0x4034	/* AESU interrupt status register */
++#define TALITOS_AESUICR		0x4038	/* AESU interrupt control register */
++#define TALITOS_AESUICR_HI	0x403c	/* AESU interrupt control register */
++#define TALITOS_MDEUISR		0x6030	/* MDEU interrupt status register */
++#define TALITOS_MDEUISR_HI	0x6034	/* MDEU interrupt status register */
++#define TALITOS_RNGSR		0xa028	/* RNG status register */
++#define TALITOS_RNGSR_HI	0xa02c	/* RNG status register */
++#define TALITOS_RNGSR_HI_RD	0x1	/* RNG Reset done */
++#define TALITOS_RNGSR_HI_OFL	0xff0000/* number of dwords in RNG output FIFO*/
++#define TALITOS_RNGDSR		0xa010	/* RNG data size register */
++#define TALITOS_RNGDSR_HI	0xa014	/* RNG data size register */
++#define TALITOS_RNG_FIFO	0xa800	/* RNG FIFO - pool of random numbers */
++#define TALITOS_RNGISR		0xa030	/* RNG Interrupt status register */
++#define TALITOS_RNGISR_HI	0xa034	/* RNG Interrupt status register */
++#define TALITOS_RNGRCR		0xa018	/* RNG Reset control register */
++#define TALITOS_RNGRCR_HI	0xa01c	/* RNG Reset control register */
++#define TALITOS_RNGRCR_HI_SR	0x1	/* RNG RNGRCR:Software Reset */
++
++/* descriptor pointer entry */
++struct talitos_desc_ptr {
++	u16	len;		/* length */
++	u8	extent;		/* jump (to s/g link table) and extent */
++	u8	res;		/* reserved */
++	u32	ptr;		/* pointer */
++};
++
++/* descriptor */
++struct talitos_desc {
++	u32	hdr;				/* header */
++	u32	res;				/* reserved */
++	struct talitos_desc_ptr		ptr[7];	/* ptr/len pair array */
++};
++
++/* talitos descriptor header (hdr) bits */
++
++/* primary execution unit select */
++#define	TALITOS_SEL0_AFEU	0x10000000
++#define	TALITOS_SEL0_DEU	0x20000000
++#define	TALITOS_SEL0_MDEU	0x30000000
++#define	TALITOS_SEL0_RNG	0x40000000
++#define	TALITOS_SEL0_PKEU	0x50000000
++#define	TALITOS_SEL0_AESU	0x60000000
++
++/* primary execution unit mode (MODE0) and derivatives */
++#define	TALITOS_MODE0_AESU_CBC		0x00200000
++#define	TALITOS_MODE0_AESU_ENC		0x00100000
++#define	TALITOS_MODE0_DEU_CBC		0x00400000
++#define	TALITOS_MODE0_DEU_3DES		0x00200000
++#define	TALITOS_MODE0_DEU_ENC		0x00100000
++#define	TALITOS_MODE0_MDEU_INIT		0x01000000	/* init starting regs */
++#define	TALITOS_MODE0_MDEU_HMAC		0x00800000
++#define	TALITOS_MODE0_MDEU_PAD		0x00400000	/* PD */
++#define	TALITOS_MODE0_MDEU_MD5		0x00200000
++#define	TALITOS_MODE0_MDEU_SHA256	0x00100000
++#define	TALITOS_MODE0_MDEU_SHA1		0x00000000	/* SHA-160 */
++#define	TALITOS_MODE0_MDEU_MD5_HMAC	\
++		(TALITOS_MODE0_MDEU_MD5 | TALITOS_MODE0_MDEU_HMAC)
++#define	TALITOS_MODE0_MDEU_SHA256_HMAC	\
++		(TALITOS_MODE0_MDEU_SHA256 | TALITOS_MODE0_MDEU_HMAC)
++#define	TALITOS_MODE0_MDEU_SHA1_HMAC	\
++		(TALITOS_MODE0_MDEU_SHA1 | TALITOS_MODE0_MDEU_HMAC)
++
++/* secondary execution unit select (SEL1) */
++/* it's MDEU or nothing */
++#define	TALITOS_SEL1_MDEU	0x00030000
++
++/* secondary execution unit mode (MODE1) and derivatives */
++#define	TALITOS_MODE1_MDEU_INIT		0x00001000	/* init starting regs */
++#define	TALITOS_MODE1_MDEU_HMAC		0x00000800
++#define	TALITOS_MODE1_MDEU_PAD		0x00000400	/* PD */
++#define	TALITOS_MODE1_MDEU_MD5		0x00000200
++#define	TALITOS_MODE1_MDEU_SHA256	0x00000100
++#define	TALITOS_MODE1_MDEU_SHA1		0x00000000	/* SHA-160 */
++#define	TALITOS_MODE1_MDEU_MD5_HMAC	\
++	(TALITOS_MODE1_MDEU_MD5 | TALITOS_MODE1_MDEU_HMAC)
++#define	TALITOS_MODE1_MDEU_SHA256_HMAC	\
++	(TALITOS_MODE1_MDEU_SHA256 | TALITOS_MODE1_MDEU_HMAC)
++#define	TALITOS_MODE1_MDEU_SHA1_HMAC	\
++	(TALITOS_MODE1_MDEU_SHA1 | TALITOS_MODE1_MDEU_HMAC)
++
++/* direction of overall data flow (DIR) */
++#define	TALITOS_DIR_OUTBOUND	0x00000000
++#define	TALITOS_DIR_INBOUND	0x00000002
++
++/* done notification (DN) */
++#define	TALITOS_DONE_NOTIFY	0x00000001
++
++/* descriptor types */
++/* odd numbers here are valid on SEC2 and greater only (e.g. ipsec_esp) */
++#define TD_TYPE_AESU_CTR_NONSNOOP	(0 << 3)
++#define TD_TYPE_IPSEC_ESP		(1 << 3)
++#define TD_TYPE_COMMON_NONSNOOP_NO_AFEU	(2 << 3)
++#define TD_TYPE_HMAC_SNOOP_NO_AFEU	(4 << 3)
++
++#define TALITOS_HDR_DONE_BITS	0xff000000
++
++#define	DPRINTF(a...)	do { \
++						if (debug) { \
++							printk("%s: ", sc ? \
++								device_get_nameunit(sc->sc_cdev) : "talitos"); \
++							printk(a); \
++						} \
++					} while (0)
+diff -urN linux-2.6.23.16.old/crypto/ocf/talitos/talitos_soft.h linux-2.6.23.16/crypto/ocf/talitos/talitos_soft.h
+--- linux-2.6.23.16.old/crypto/ocf/talitos/talitos_soft.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/talitos/talitos_soft.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,77 @@
++/*
++ * Freescale SEC data structures for integration with ocf-linux
++ *
++ * Copyright (c) 2006 Freescale Semiconductor, Inc.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/*
++ * paired descriptor and associated crypto operation
++ */
++struct desc_cryptop_pair {
++	struct talitos_desc	cf_desc;	/* descriptor ptr */
++	struct cryptop		*cf_crp;	/* cryptop ptr */
++};
++
++/*
++ * Holds data specific to a single talitos device.
++ */
++struct talitos_softc {
++	softc_device_decl	sc_cdev;
++	struct platform_device	*sc_dev;	/* device backpointer */
++	ocf_iomem_t		sc_base_addr;
++	int			sc_irq;
++	int			sc_num;		/* if we have multiple chips */
++	int32_t			sc_cid;		/* crypto tag */
++	u64			sc_chiprev;	/* major/minor chip revision */
++	int			sc_nsessions;
++	struct talitos_session	*sc_sessions;
++	int			sc_num_channels;/* number of crypto channels */
++	int			sc_chfifo_len;	/* channel fetch fifo len */
++	int			sc_exec_units;	/* execution units mask */
++	int			sc_desc_types;	/* descriptor types mask */
++	/*
++	 * mutual exclusion for intra-channel resources, e.g. fetch fifos
++	 * the last entry is a meta-channel lock used by the channel scheduler
++	 */
++	spinlock_t		*sc_chnfifolock;
++	/* sc_chnlastalgo contains last algorithm for that channel */
++	int			*sc_chnlastalg;
++	/* sc_chnfifo holds pending descriptor--crypto operation pairs */
++	struct desc_cryptop_pair	**sc_chnfifo;
++};
++
++struct talitos_session {
++	u_int32_t	ses_used;
++	u_int32_t	ses_klen;		/* key length in bits */
++	u_int32_t	ses_key[8];		/* DES/3DES/AES key */
++	u_int32_t	ses_hmac[5];		/* hmac inner state */
++	u_int32_t	ses_hmac_len;		/* hmac length */
++	u_int32_t	ses_iv[4];		/* DES/3DES/AES iv */
++	u_int32_t	ses_mlen;		/* desired hash result len (12=ipsec or 16) */
++};
++
++#define	TALITOS_SESSION(sid)	((sid) & 0x0fffffff)
++#define	TALITOS_SID(crd, sesn)	(((crd) << 28) | ((sesn) & 0x0fffffff))
+diff -urN linux-2.6.23.16.old/crypto/ocf/uio.h linux-2.6.23.16/crypto/ocf/uio.h
+--- linux-2.6.23.16.old/crypto/ocf/uio.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.23.16/crypto/ocf/uio.h	2008-02-26 09:29:13.000000000 -0500
+@@ -0,0 +1,54 @@
++#ifndef _OCF_UIO_H_
++#define _OCF_UIO_H_
++
++#include <linux/uio.h>
++
++/*
++ * The linux uio.h doesn't have all we need.  To be fully api compatible
++ * with the BSD cryptodev,  we need to keep this around.  Perhaps this can
++ * be moved back into the linux/uio.h
++ *
++ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
++ * Copyright (C) 2006-2007 David McCullough
++ * Copyright (C) 2004-2005 Intel Corporation.
++ *
++ * LICENSE TERMS
++ *
++ * The free distribution and use of this software in both source and binary
++ * form is allowed (with or without changes) provided that:
++ *
++ *   1. distributions of this source code include the above copyright
++ *      notice, this list of conditions and the following disclaimer;
++ *
++ *   2. distributions in binary form include the above copyright
++ *      notice, this list of conditions and the following disclaimer
++ *      in the documentation and/or other associated materials;
++ *
++ *   3. the copyright holder's name is not used to endorse products
++ *      built using this software without specific written permission.
++ *
++ * ALTERNATIVELY, provided that this notice is retained in full, this product
++ * may be distributed under the terms of the GNU General Public License (GPL),
++ * in which case the provisions of the GPL apply INSTEAD OF those given above.
++ *
++ * DISCLAIMER
++ *
++ * This software is provided 'as is' with no explicit or implied warranties
++ * in respect of its properties, including, but not limited to, correctness
++ * and/or fitness for purpose.
++ * ---------------------------------------------------------------------------
++ */
++
++struct uio {
++	struct	iovec *uio_iov;
++	int		uio_iovcnt;
++	off_t	uio_offset;
++	int		uio_resid;
++#if 0
++	enum	uio_seg uio_segflg;
++	enum	uio_rw uio_rw;
++	struct  thread *uio_td;
++#endif
++};
++
++#endif
+diff -urN linux-2.6.23.16.old/drivers/char/random.c linux-2.6.23.16/drivers/char/random.c
+--- linux-2.6.23.16.old/drivers/char/random.c	2008-02-26 09:27:00.000000000 -0500
++++ linux-2.6.23.16/drivers/char/random.c	2008-02-26 09:29:13.000000000 -0500
+@@ -129,6 +129,9 @@
+  *                                unsigned int value);
+  * 	void add_interrupt_randomness(int irq);
+  *
++ *      void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
++ *      int random_input_wait(void);
++ *
+  * add_input_randomness() uses the input layer interrupt timing, as well as
+  * the event type information from the hardware.
+  *
+@@ -140,6 +143,13 @@
+  * a better measure, since the timing of the disk interrupts are more
+  * unpredictable.
+  *
++ * random_input_words() just provides a raw block of entropy to the input
++ * pool, such as from a hardware entropy generator.
++ *
++ * random_input_wait() suspends the caller until such time as the
++ * entropy pool falls below the write threshold, and returns a count of how
++ * much entropy (in bits) is needed to sustain the pool.
++ *
+  * All of these routines try to estimate how many bits of randomness a
+  * particular randomness source.  They do this by keeping track of the
+  * first and second order deltas of the event timings.
+@@ -671,6 +681,61 @@
+ EXPORT_SYMBOL(add_disk_randomness);
+ #endif
+ 
++/*
++ * random_input_words - add bulk entropy to pool
++ *
++ * @buf: buffer to add
++ * @wordcount: number of __u32 words to add
++ * @ent_count: total amount of entropy (in bits) to credit
++ *
++ * this provides bulk input of entropy to the input pool
++ *
++ */
++void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
++{
++	add_entropy_words(&input_pool, buf, wordcount);
++
++	credit_entropy_store(&input_pool, ent_count);
++
++	DEBUG_ENT("crediting %d bits => %d\n",
++		  ent_count, input_pool.entropy_count);
++	/*
++	 * Wake up waiting processes if we have enough
++	 * entropy.
++	 */
++	if (input_pool.entropy_count >= random_read_wakeup_thresh)
++		wake_up_interruptible(&random_read_wait);
++}
++EXPORT_SYMBOL(random_input_words);
++
++/*
++ * random_input_wait - wait until random needs entropy
++ *
++ * this function sleeps until the /dev/random subsystem actually
++ * needs more entropy, and then return the amount of entropy
++ * that it would be nice to have added to the system.
++ */
++int random_input_wait(void)
++{
++	int count;
++
++	wait_event_interruptible(random_write_wait, 
++			 input_pool.entropy_count < random_write_wakeup_thresh);
++
++	count = random_write_wakeup_thresh - input_pool.entropy_count;
++
++        /* likely we got woken up due to a signal */
++	if (count <= 0) count = random_read_wakeup_thresh; 
++
++	DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n",
++		  count,
++		  input_pool.entropy_count, random_write_wakeup_thresh);
++
++	return count;
++}
++EXPORT_SYMBOL(random_input_wait);
++
++
+ #define EXTRACT_SIZE 10
+ 
+ /*********************************************************************
+diff -urN linux-2.6.23.16.old/fs/fcntl.c linux-2.6.23.16/fs/fcntl.c
+--- linux-2.6.23.16.old/fs/fcntl.c	2008-02-26 09:26:41.000000000 -0500
++++ linux-2.6.23.16/fs/fcntl.c	2008-02-26 09:29:13.000000000 -0500
+@@ -198,6 +198,7 @@
+ 		ret = dupfd(file, 0);
+ 	return ret;
+ }
++EXPORT_SYMBOL(sys_dup);
+ 
+ #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME)
+ 
+diff -urN linux-2.6.23.16.old/include/linux/miscdevice.h linux-2.6.23.16/include/linux/miscdevice.h
+--- linux-2.6.23.16.old/include/linux/miscdevice.h	2008-02-26 09:26:42.000000000 -0500
++++ linux-2.6.23.16/include/linux/miscdevice.h	2008-02-26 09:29:13.000000000 -0500
+@@ -12,6 +12,7 @@
+ #define APOLLO_MOUSE_MINOR 7
+ #define PC110PAD_MINOR 9
+ /*#define ADB_MOUSE_MINOR 10	FIXME OBSOLETE */
++#define CRYPTODEV_MINOR		70	/* /dev/crypto */
+ #define WATCHDOG_MINOR		130	/* Watchdog timer     */
+ #define TEMP_MINOR		131	/* Temperature Sensor */
+ #define RTC_MINOR 135
+diff -urN linux-2.6.23.16.old/include/linux/random.h linux-2.6.23.16/include/linux/random.h
+--- linux-2.6.23.16.old/include/linux/random.h	2008-02-26 09:26:42.000000000 -0500
++++ linux-2.6.23.16/include/linux/random.h	2008-02-26 09:29:13.000000000 -0500
+@@ -8,6 +8,7 @@
+ #define _LINUX_RANDOM_H
+ 
+ #include <linux/ioctl.h>
++#include <linux/types.h> /* for __u32 in user space */
+ 
+ /* ioctl()'s for the random number generator */
+ 
+@@ -48,6 +49,10 @@
+ 				 unsigned int value);
+ extern void add_interrupt_randomness(int irq);
+ 
++extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count);
++extern int random_input_wait(void);
++#define HAS_RANDOM_INPUT_WAIT 1
++
+ extern void get_random_bytes(void *buf, int nbytes);
+ void generate_random_uuid(unsigned char uuid_out[16]);
+ 
diff -Nur kamikaze_7.09.orig/target/linux/generic-2.6/patches-2.6.22/411-geode_aes-corrupted_mac.patch kamikaze_7.09/target/linux/generic-2.6/patches-2.6.22/411-geode_aes-corrupted_mac.patch
--- kamikaze_7.09.orig/target/linux/generic-2.6/patches-2.6.22/411-geode_aes-corrupted_mac.patch	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/target/linux/generic-2.6/patches-2.6.22/411-geode_aes-corrupted_mac.patch	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,34 @@
+diff -urN linux-2.6.23.16.old/drivers/crypto/geode-aes.c linux-2.6.23.16/drivers/crypto/geode-aes.c
+--- linux-2.6.23.16.old/drivers/crypto/geode-aes.c	2008-02-26 11:48:45.000000000 -0500
++++ linux-2.6.23.16/drivers/crypto/geode-aes.c	2008-02-26 11:50:23.000000000 -0500
+@@ -87,9 +87,10 @@
+ 	/* Start the operation */
+ 	iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
+ 
+-	do
++	do {
+ 		status = ioread32(_iobase + AES_INTR_REG);
+-	while(!(status & AES_INTRA_PENDING) && --counter);
++		cpu_relax();
++	} while(!(status & AES_INTRA_PENDING) && --counter);
+ 
+ 	/* Clear the event */
+ 	iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
+@@ -101,6 +102,7 @@
+ {
+ 	u32 flags = 0;
+ 	unsigned long iflags;
++	int ret;
+ 
+ 	if (op->len == 0)
+ 		return 0;
+@@ -129,7 +131,8 @@
+ 		_writefield(AES_WRITEKEY0_REG, op->key);
+ 	}
+ 
+-	do_crypt(op->src, op->dst, op->len, flags);
++	ret = do_crypt(op->src, op->dst, op->len, flags);
++	BUG_ON(ret);
+ 
+ 	if (op->mode == AES_MODE_CBC)
+ 		_readfield(AES_WRITEIV0_REG, op->iv);
diff -Nur kamikaze_7.09.orig/target/linux/x86-2.6/config/default kamikaze_7.09/target/linux/x86-2.6/config/default
--- kamikaze_7.09.orig/target/linux/x86-2.6/config/default	2007-09-20 10:54:17.000000000 +0200
+++ kamikaze_7.09/target/linux/x86-2.6/config/default	2008-06-19 17:34:17.000000000 +0200
@@ -65,6 +65,7 @@
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_TABLE=y
 CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_HW=y
 CONFIG_CRYPTO_DEV_GEODE=m
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_CRYPTO_TWOFISH_586=m
@@ -115,9 +116,9 @@
 CONFIG_HW_CONSOLE=y
 CONFIG_HW_RANDOM=y
 # CONFIG_HW_RANDOM_AMD is not set
-CONFIG_HW_RANDOM_GEODE=y
+CONFIG_HW_RANDOM_GEODE=m
 # CONFIG_HW_RANDOM_INTEL is not set
-CONFIG_HW_RANDOM_VIA=y
+CONFIG_HW_RANDOM_VIA=m
 CONFIG_I2C=m
 CONFIG_I2C_ALGOBIT=m
 CONFIG_I2C_BOARDINFO=y
@@ -170,6 +171,7 @@
 CONFIG_LEDS_NET48XX=m
 # CONFIG_LEDS_TRIGGER_IDE_DISK is not set
 # CONFIG_LEDS_WRAP is not set
+CONFIG_LEDS_ALIX=m
 # CONFIG_LIBERTAS is not set
 # CONFIG_M386 is not set
 CONFIG_M486=y
@@ -424,3 +426,17 @@
 # CONFIG_X86_VOYAGER is not set
 CONFIG_X86_WP_WORKS_OK=y
 CONFIG_X86_XADD=y
+CONFIG_OCF_OCF=m
+CONFIG_OCF_CRYPTODEV=m
+CONFIG_OCF_CRYPTOSOFT=m
+# CONFIG_OCF_RANDOMHARVEST is not set
+# CONFIG_OCF_FIPS is not set
+# CONFIG_OCF_SAFE is not set
+# CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_IXP4XX_SHA1_MD5 is not set
+# CONFIG_OCF_HIFN is not set
+# CONFIG_OCF_HIFNHIPP is not set
+# CONFIG_OCF_TALITOS is not set
+# CONFIG_OCF_OCFNULL is not set
+# CONFIG_OCF_BENCH is not set
+
diff -Nur kamikaze_7.09.orig/target/linux/x86-2.6/image/grub/menu.lst kamikaze_7.09/target/linux/x86-2.6/image/grub/menu.lst
--- kamikaze_7.09.orig/target/linux/x86-2.6/image/grub/menu.lst	2007-09-20 10:54:12.000000000 +0200
+++ kamikaze_7.09/target/linux/x86-2.6/image/grub/menu.lst	2008-06-19 17:34:17.000000000 +0200
@@ -1,15 +1,15 @@
 serial --unit=0 --speed=@BAUDRATE@ --word=8 --parity=no --stop=1
-terminal --timeout=10 console serial
+terminal --timeout=3 serial
 
 default 0
 timeout 5
 
 title   OpenWrt
 root    (hd0,0)
-kernel  /boot/vmlinuz @CMDLINE@ noinitrd console=tty0 console=ttyS0,@BAUDRATE@n8 reboot=bios
+kernel  /boot/vmlinuz @CMDLINE@ ro noinitrd console=ttyS0,@BAUDRATE@n8 reboot=bios
 boot
 
 title	OpenWrt (failsafe)
 root	(hd0,0)
-kernel  /boot/vmlinuz failsafe=true @CMDLINE@ noinitrd console=tty0 console=ttyS0,@BAUDRATE@n8 reboot=bios
+kernel  /boot/vmlinuz failsafe=true @CMDLINE@ ro noinitrd console=ttyS0,@BAUDRATE@n8 reboot=bios
 boot
diff -Nur kamikaze_7.09.orig/target/linux/x86-2.6/profiles/Alix.mk kamikaze_7.09/target/linux/x86-2.6/profiles/Alix.mk
--- kamikaze_7.09.orig/target/linux/x86-2.6/profiles/Alix.mk	1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/target/linux/x86-2.6/profiles/Alix.mk	2008-06-19 17:34:17.000000000 +0200
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Alix
+  NAME:=PCEngines Alix 2 and 3 boards
+  PACKAGES:=kmod-via-rhine kmod-leds-alix kmod-hw-rng kmod-hw-crypto kmod-linux-ocf libopenssl-cryptodev
+endef
+
+define Profile/Alix/Description
+        Package set compatible with the PCEngines ALIX 2 and 3 boards. Contains VIA Rhine III VT6105M, LED, and Crytpo support
+endef
+$(eval $(call Profile,Alix))
